---------- android培訓 java培訓 期待與您交流!------------
先上需求:
銀行業務調度系統
模擬實現銀行業務調度系統邏輯,具體需求如下:
銀行內有6個業務窗口,1- 4號窗口爲普通窗口,5號窗口爲快速窗口,6號窗口爲VIP窗口。
有三種對應類型的客戶:VIP客戶,普通客戶,快速客戶(辦理如交水電費、電話費之類業務的客戶)。
異步隨機生成各種類型的客戶,生成各類型用戶的概率比例爲:
VIP客戶 :普通客戶 :快速客戶 = 1 :6 :3。
客戶辦理業務所需時間有最大值和最小值,在該範圍內隨機設定每個VIP客戶以及普通客戶辦理業務所需的時間,快速客戶辦理業務所需時間爲最小值(提示:辦理業務的過程可通過線程Sleep的方式模擬)。
各類型客戶在其對應窗口按順序依次辦理業務。
當VIP(6號)窗口和快速業務(5號)窗口沒有客戶等待辦理業務的時候,這兩個窗口可以處理普通客戶的業務,而一旦有對應的客戶等待辦理業務的時候,則優先處理對應客戶的業務。
隨機生成客戶時間間隔以及業務辦理時間最大值和最小值自定,可以設置。
不要求實現GUI,只考慮系統邏輯實現,可通過Log方式展現程序運行結果。
--------------------------------------------------------------------------------------------------------------
分析:
客戶進入銀行先分類型取票排隊,然後等待服務窗口叫號。所以我覺得計數器應該擁有客戶排隊的數據,那麼編號就當作是一個個客戶,計數器就擁有對外訪問客戶的方法,而窗口就向計數器詢問有沒有下一個客戶,如果沒有就換普通類型再詢問有沒有,如果始終沒有下一個客戶,那麼就休息一下再繼續
快速窗口和vip窗口在沒有對應客戶的情況下還要爲普通客戶服務。所以窗口類中應該有判斷類型的方法
由於服務的時間有最大值和最小值,爲了體現面向對象的思想,就將時間封裝成一個類。
下面就進行代碼的分析,自己沒有照着老師教的抄,而是以自己的思想做一遍,體會其中的差距,理解老師每一步爲什麼要那麼做。
最後總結分析出自己雖然也能將代碼做出來,但沒有將任何事物看作對象來對待,面向對象的體會也許就只能在實際的項目經驗中去積累。
窗口類型:
/**
* 由於窗口類型是不變的,分別對應 普通 快速 VIP
* @author 不信
*
*/
public enum windowType {
COMMON,FAST,VIP;
//覆蓋父類的toString()
public String toString()
{
switch (this) {
case COMMON:
return "普通";
case FAST:
return "快速";
default:
return name();
}
}
//用戶類型對應服務時間,其中快速客戶爲最小值也就是1秒
public int useTime()
{
if(this != FAST)
return Constants.MAX_SERVICE_TIME;
else {
return Constants.MIN_SERVICE_TIME;
}
}
}
服務時間的最大值和最小值:
/**
* 服務時間的最小值與最大值
* @author 不信
*
*/
public class Constants {
public static int MAX_SERVICE_TIME = 10; //10秒!
public static int MIN_SERVICE_TIME = 1; //1秒!
}
計數器,裏面包含了客戶的排隊順序
import java.util.LinkedList;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* 這是一個計數器類,由於顧客領了票就說明排了隊,所以計數器擁有顧客
* 服務窗口可以問計數器有沒有顧客
*
* */
public class counter {
//顧客排隊的號
private int num = 1;
//顧客類型不一樣,辦理業務所用的時間也就不一樣
private int time;
//顧客類型
private windowType type;
//存儲顧客排隊的號
private LinkedList<Integer> list = new LinkedList<Integer>();
//計數器類是一開始就有類型與辦理業務所需的最大時間
public counter(int time,windowType type)
{
this.time = time;
this.type = type;
addList();
}
//定時進入一位顧客,由於顧客類型的不一樣,光臨的時間也不一樣
public synchronized void addList()
{
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable() {
@Override
public void run() {
list.addLast(num++);
}
},
0,
time,
TimeUnit.SECONDS
);
System.out.println("第"+num+"位"+type.toString()+"客戶等待服務");
}
//服務窗口調用這個方法來獲取正在排隊的客戶,如果沒有返回null
public synchronized Integer take()
{
if(!list.isEmpty())
return list.removeFirst();
else {
return null;
}
}
}
三種窗口類型對應了三種客戶類型
/**
* 三種客戶類型的對象,提供對外訪問的靜態方法,服務窗口其實就是根據類型來訪問的
* @author 不信
*
*/
public class client {
private static counter COMMONCLIENT = new counter(1, windowType.COMMON);
private static counter FASTCLIENT = new counter(3,windowType.FAST);
private static counter VIPCLIENT = new counter(6, windowType.VIP);
private client(){}
public static counter getClient(windowType type)
{
switch (type) {
case COMMON:
return COMMONCLIENT;
case FAST:
return FASTCLIENT;
default:
return VIPCLIENT;
}
}
服務窗口
import java.util.Random;
import java.util.concurrent.Executors;
/**
* 服務窗口類
* @author 不信
*
*/
public class window {
//每個窗口都有自己對應的類型
private windowType type;
//每個窗口都有自己的編號
private int num;
//在初始化時,就有了類型和編號
public window(windowType type, int num)
{
this.type = type;
this.num = num;
}
//窗口開始工作
public void windower()
{
System.out.println("第"+num+"號"+this.type+"窗口開始服務");
//創建一個線程池,其中只有一個線程
Executors.newSingleThreadExecutor().execute(new Runnable() {
@Override
public void run() {
while(true)
{
System.out.println("第"+num+"號"+window.this.type+"窗口正在等待客戶");
//調用窗口的工作內容
work(type);
}
}
});
}
//窗口工作的內容
public void work(windowType type)
{
//窗口尋找對應類型的客戶是否存在,如果存在就給予服務,如果不存在就執行 else if()
Integer i = client.getClient(type).take();
if(i!=null){
System.out.println("第"+num+"號"+this.type+"窗口正在爲第"+i+"位"
+type+"客戶服務");
//以客戶的類型計算出要給服務的時間
int randomTime = new Random().nextInt(type.useTime())+1;
try {
//這裏以線程 sleep()的形式模仿
Thread.sleep(randomTime*1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//當線程“醒”來時,就給對應得客戶服務完畢
System.out.println("第"+num+"號"+this.type+"窗口爲第"+i+"位"
+type+"客戶服務耗時"+randomTime+"秒");
}
//由於vip窗口和快速窗口在沒有對應客戶存在的情況下,還要給普通客戶服務所以這裏使用了遞歸
else if(type != windowType.COMMON)
{
work(windowType.COMMON);
}
else{
//如果始終沒有需要服務的客戶,就sleep()休息一秒,醒來繼續查找
System.out.println("第"+num+"號"+this.type+"窗口沒有取到任務,正在休息一秒");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
最後主函數調用:
public class MainClass {
public static void main(String[] args)
{
//四個普通窗口
for(int i = 1;i < 5;i++)
{
new window(windowType.COMMON, i).windower();
}
//一個快速窗口 和一個VIP窗口
new window(windowType.FAST, 5).windower();
new window(windowType.VIP, 6).windower();
}
}
運行結果如圖
---------- android培訓 java培訓 期待與您交流!------------
詳情請點擊:http://edu.csdn.net/