---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity開發</a>、<a href="http://www.itheima.com"target="blank">.Net培訓</a>、期待與您交流! ----------------------
銀行業務調度系統
需求:
1,銀行內有6個業務窗口,1-4號窗口爲普通窗口,5號窗口爲快速窗口,
6號窗口爲VIP窗口。
2,有三種對應類型的客戶:VIP,普通客戶,快速客戶(辦理如交水電費,話費之類的業務的客戶)。
3,異步隨機生成各種業務類型的客戶,生成各類型的客戶的比例爲:
VIP客戶:快速客戶:普通客戶 = 1:3:6。
4,客戶辦理業務所需時間有最大值和最小值,在該範圍內隨機設定每個VIP客戶
以及普通客戶辦理業務所需的時間,快速客戶辦理業務所需的時間爲最小值。
5,各類型客戶在器對應窗口按順序依次辦理業務。
6,當VIP(6號)窗口和快速業務(5號)窗口沒有客戶等待辦理業務的時候,
這兩個窗口可以處理普通客戶的業務,而一旦有對應的客戶等待辦理業務時,則優先處理對應客戶的業務。
7,隨機生成客戶的時間間隔及業務辦理時間的最大值和最小值自定。
分析:
1,客戶:要去銀行辦理業務的人。
2,取號:去銀行辦理業務的時候,都會取票排隊,所以有一個取票器。
3,出票:而不同的客戶辦理的業務也是不同的,按需求分出了三類客戶,那麼就有三個產生不同類型票號的票號管理器。
4,辦理業務:顧客取到號排隊後,交道號之後就要去辦理業務,所以要有辦理業務的窗口。
客戶:
1,因爲客戶要辦理的業務是不同的,但客戶的類型是固定的,所以要有一個用於描述客戶的類。
取號:
1,客戶來了之後就要取票辦理業務,所以取票器要有產生客戶號的方法;
2,而客戶的數量是不固定的,所以取票器要有一個集合來存儲客戶。
3,當一個顧客辦理完業務之後,就要把後面的客戶的排隊順序向前移一位,所以要有一個移出辦理業務結束的客戶的方法。
出票:
1,因爲業務的不同,所以取票器中,要有三個不同的票號管理器;
辦理業務:
1,窗口會定時的叫號,對應業務的客戶被叫到號後就會到對應的窗口辦理業務,這就要問出票器有沒有對應的票號;
2,窗口辦理完業務之後,就會要叫下一個號,如果快速窗口和VIP窗口沒有客戶,則就去辦理普通業務。
對應類的示例代碼:
票號管理器類:
爲客戶生產對應類型業務的票號,當客戶辦理完業務時,取出對應的票號。
package com.itheima.bank;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 票號管理器
* @author wuyong
*
*/
public class NOManager {
//票號
private Integer lastNO = 1;
private List queueNos = new ArrayList();
/**
* 創建票號
* @return
*/
public synchronized Integer generateNewNO(){
queueNos.add(lastNO);
return lastNO ++;
}
/**
* 獲得當前服務的號碼
* @return
*/
public synchronized Integer fetchServiceNO(){
if (queueNos.size() > 0)
return queueNos.remove(0);
return null;
}
}
取票器類:
因爲,每一個客戶到銀行取號,都是到取票器取號的,所以取票器用單例設計。
package com.itheima.bank;
/**
* 出票器。
* @author wuyong
*
*/
public class NOMachine {
//普通的票號管理器
private NOManager commonManager = new NOManager();
//快速的票號管理器
private NOManager expressManager = new NOManager();
//VIP的票號管理器
private NOManager vipManager = new NOManager();
public NOManager getCommonManager() {
return commonManager;
}
public NOManager getExpressManager() {
return expressManager;
}
public NOManager getVipManager() {
return vipManager;
}
/**
* 單例模式
*/
private static final NOMachine instance = new NOMachine();
private NOMachine(){}
public static NOMachine getInsatnce(){
return instance;
}
}
服務窗口類:
生產4個普通窗口,1個快速窗口,1個VIP窗口,辦理三種類型的業務。
package com.itheima.bank;
import java.util.Random;
import java.util.concurrent.Executors;
/**
* 窗口
* @author wuyong
*
*/
public class ServiceWindow {
//用戶的類型
private CustomerType type = CustomerType.COMMON;
//窗口編號
private int windowId = 1;
public void setType(CustomerType type) {
this.type = type;
}
public void setWindowId(int windowId) {
this.windowId = windowId;
}
//取票器
private NOMachine noMachine = NOMachine.getInsatnce();
public void start(){
Executors.newSingleThreadExecutor().execute(
new Runnable() {
public void run() {
while (true) {
switch (type) {
case COMMON:
commonService();
break;
case EXPRESS:
expressService();
break;
case VIP:
vipService();
break;
}
}
}
}
);
}
private void commonService() {
Integer no = noMachine.getCommonManager().fetchServiceNO();
String windowName = "第" + windowId + "號" + type +"窗口";
System.out.println(windowName + "正在獲取任務");
if (no != null) {
System.out.println(windowName + "開始爲第" + no + "個普通客戶服務");
long startTime = System.currentTimeMillis();
int maxServiceTime = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
int serviceTime = new Random().nextInt(maxServiceTime) + Constants.MIN_SERVICE_TIME;
try {
Thread.sleep(serviceTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
int usedTime = (int)(System.currentTimeMillis() - startTime) / 1000;
System.out.println(windowName + "爲第" + no + "個普通客戶完成了業務,耗時:" + usedTime + "秒");
}
else {
System.out.println(windowName + "沒有獲得任務!空閒一秒鐘!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void expressService() {
Integer no = noMachine.getExpressManager().fetchServiceNO();
String windowName = "第" + windowId + "號" + type +"窗口";
System.out.println(windowName + "正在獲取任務");
if (no != null) {
System.out.println(windowName + "開始爲第" + no + "個快速客戶服務");
long startTime = System.currentTimeMillis();
long serviceTime = Constants.MIN_SERVICE_TIME;
try {
Thread.sleep(serviceTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
int usedTime = (int)(System.currentTimeMillis() - startTime) / 1000;
System.out.println(windowName + "爲第" + no + "個快速客戶完成了業務,耗時:" + usedTime + "秒");
}
else {
System.out.println(windowName + "沒有獲得任務!");
commonService();
}
}
private void vipService() {
String windowName = "第" + windowId + "號" + type +"窗口";
Integer no = noMachine.getVipManager().fetchServiceNO();
System.out.println(windowName + "正在獲取任務");
if (no != null) {
System.out.println(windowName + "開始爲第" + no + "個VIP客戶服務");
long startTime = System.currentTimeMillis();
int maxServiceTime = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
int serviceTime = new Random().nextInt(maxServiceTime) + Constants.MIN_SERVICE_TIME;
try {
Thread.sleep(serviceTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
int usedTime = (int)(System.currentTimeMillis() - startTime) / 1000;
System.out.println(windowName + "爲第" + no + "個VIP客戶完成了業務,耗時:" + usedTime + "秒");
}
else {
System.out.println(windowName + "沒有獲得任務!");
commonService();
}
}
}
package com.itheima.bank;
/**
* 客戶類型
* 類型爲枚舉
* @author wuyong
*
*/
public enum CustomerType {
COMMON,EXPRESS,VIP;
//獲取對應類型的名稱
public String toString(){
switch(this){
case COMMON:
return "普通";
case EXPRESS:
return "快速";
case VIP:
return name();
}
return null;
}
}
package com.itheima.bank;
/**
* 服務時間的相關信息
* @author wuyong
*
*/
public class Constants {
//服務的最大時間
public static int MAX_SERVICE_TIME = 10 * 1000;
//服務的最小時間
public static int MIN_SERVICE_TIME = 1 * 1000;
//普通客戶出現的時間
public static int COMMON_SREVICE_TIME = 1;
}
package com.itheima.bank;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* 主線程類
* @author wuyong
*
*/
public class MainClass {
/**
* @param args
*/
public static void main(String[] args) {
//1~4號普通窗口
for (int i = 1; i < 5; i++) {
ServiceWindow commonWindow = new ServiceWindow();
commonWindow.setWindowId(i);
commonWindow.start();
}
//快速窗口
ServiceWindow expressWindow = new ServiceWindow();
expressWindow.setType(CustomerType.EXPRESS);
expressWindow.start();
//VIP窗口
ServiceWindow vipWindow = new ServiceWindow();
vipWindow.setType(CustomerType.VIP);
vipWindow.start();
//定時生產一個普通客戶,等待服務
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable() {
@Override
public void run() {
Integer no = NOMachine.getInsatnce().getCommonManager().generateNewNO();
System.out.println(no + "號普通客戶等待服務。。。");
}
},
0,
Constants.COMMON_SREVICE_TIME,
TimeUnit.SECONDS);
//定時生產一個VIP客戶,等待服務
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable() {
@Override
public void run() {
Integer no = NOMachine.getInsatnce().getVipManager().generateNewNO();
System.out.println(no + "號VIP客戶等待服務。。。");
}
},
0,
Constants.COMMON_SREVICE_TIME * 6,
TimeUnit.SECONDS);
//定時生產一個快速客戶,等待服務
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable() {
@Override
public void run() {
Integer no = NOMachine.getInsatnce().getExpressManager().generateNewNO();
System.out.println(no + "號快速客戶等待服務。。。");
}
},
0,
Constants.COMMON_SREVICE_TIME * 3,
TimeUnit.SECONDS);
}
}