---------------------- android培訓、java培訓、期待與您交流! ----------------------
銀行業務調度系統學習總結:
題目:
模擬實現銀行業務調度系統邏輯,具體需求如下:
1.銀行內有6個業務窗口,1 - 4號窗口爲普通窗口,5號窗口爲快速窗口,6號窗口爲VIP窗口。
2.有三種對應類型的客戶:VIP客戶,普通客戶,快速客戶(辦理如交水電費、電話費之類業務的客戶)。
3.異步隨機生成各種類型的客戶,生成各類型用戶的概率比例爲: VIP客戶 :普通客戶 :快速客戶 = 1 :6 :3。
4.客戶辦理業務所需時間有最大值和最小值,在該範圍內隨機設定每個VIP客戶以及普通客戶辦理業務所需的時間,快速客戶辦理業務所需時間爲最小值(提示:辦理業務的過程可通過線程Sleep的方式模擬)。
5.各類型客戶在其對應窗口按順序依次辦理業務。
6.當VIP(6號)窗口和快速業務(5號)窗口沒有客戶等待辦理業務的時候,這兩個窗口可以處理普通客戶的業務,而一旦有對應的客戶等待辦理業務的時候,則優先處理對應客戶的業務。
7.隨機生成客戶時間間隔以及業務辦理時間最大值和最小值自定,可以設置。
8.不要求實現GUI,只考慮系統邏輯實現,可通過Log方式展現程序運行結果。
分析:
1.分析業務邏輯確定有哪些對象
有三種對應類型的客戶:VIP客戶,普通客戶,快速客戶 ,異步隨機生成各種類型的客戶,各類型客戶在其對應窗口按順序依次辦理業務 。
通過分析,去銀行辦理業務的客戶首先要到取號機面前獲取對應的排隊序號,然後才能成爲客戶等待辦理業務,這就需要一個號碼管理器,由於有三類客戶,每類客戶的號碼編排都是完全獨立的,各自管理一類用戶的排隊號碼,
這三個號碼管理器對象統一由一個號碼機器進行管理,這個號碼機器在整個系統中始終只能有一個,所以,它要被設計成單例。
各類型客戶在其對應窗口按順序依次辦理業務,應該是窗口依次叫號。那麼還需要一個窗口對象,爲每一個客戶提供服務,即服務窗口每次找號碼管理器獲取當前要被服務的號碼。
2.通過對象計對應的類
(1).NumberManager類(號碼管理器)
定義一個用於存儲上一個客戶號碼的成員變量和用於存儲所有等待服務的客戶號碼的隊列集合。
定義一個產生新號碼的方法和獲取馬上要爲之服務的號碼的方法,這兩個方法被不同的線程操作了相同的數據,所以,要進行同步。
public class NumberManager {
private int lastNumber;
private List<Integer> queueNumbers = new ArrayList<>();
//產生新的號碼
public Integer generateNewNumber(){
queueNumbers.add(++lastNumber);
return lastNumber;
}
//獲取號碼管理中的號碼
public Integer fetchNumber(){
Integer queueNumber = null;
if(queueNumbers.size() > 0){
queueNumber = queueNumbers.remove(0);
}
return queueNumber;
}
}
(2).NumberMachine類(叫號機)
定義三個成員變量分別指向三個NumberManager對象,分別表示普通、快速和VIP客戶的號碼管理器,定義三個對應的方法來返回這三個NumberManager對象。
將NumberMachine類設計成單例。
public class NumberMachine {
//系統中只有一個叫號機,單例模式
private static final NumberMachine instance = new NumberMachine();
private NumberMachine(){}
public static NumberMachine getIntance(){
return instance;
}
//定義三個成員分別指向三個號碼管理器,並返回對應的對象
private NumberManager commonManager = new NumberManager();
private NumberManager expressManager = new NumberManager();
private NumberManager VIPManager = new NumberManager();
public NumberManager getCommonManager() {
return commonManager;
}
public NumberManager getExpressManager() {
return expressManager;
}
public NumberManager getVIPManager() {
return VIPManager;
}
}
(3).CustomerType枚舉類(客戶類型)
系統中有三種類型的客戶,所以用定義一個枚舉類,其中定義三個成員分別表示三種類型的客戶。
重寫toString方法,返回類型的中文名稱。這是在後面編碼時重構出來的,剛開始不用考慮。
public enum CustomerType {
COMMON,EXPRESS,VIP;
public String toString() {
switch(this){
case COMMON:
return "普通";
case EXPRESS:
return "快速";
case VIP:
return name();
}
return null;
};
}
(4).ServiceWindow類(服務窗口)
定義一個start方法,內部啓動一個線程,根據服務窗口的類別分別循環調用三個不同的方法。
定義三個方法分別對三種客戶進行服務,爲了觀察運行效果,應詳細打印出其中的細節信息。
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;
}
//定義一個start()方法,內部啓動一個線程叫號服務
public void start(){
Executors.newSingleThreadExecutor().execute(
new Runnable(){
@Override
public void run() {
//循環叫號
while(true){
switch(type){
case COMMON:
commonService();
break;
case EXPRESS:
expressService();
break;
case VIP:
vipService();
break;
}
}
}
});
}
/*//普通服務
public void commonService() {
//窗口名稱
String windowName = "第" + windowId + "號" + type + "窗口";
System.out.println(windowName + "開始獲取普通服務");
//客戶號碼
Integer serviceNumber = NumberMachine.getIntance().getCommonManager().fetchNumber();
if(serviceNumber != null){
System.out.println(windowName + "開始爲第" + serviceNumber + "號普通客戶服務!");
int maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
int serviceTime = new Random().nextInt(maxRandom) + 1 + Constants.MIN_SERVICE_TIME;
//Thread.sleep 模擬服務耗時
try {
Thread.sleep(serviceTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(windowName + "完成爲第" + serviceNumber + "號普通用戶服務,總共耗時:" + serviceTime / 1000 + "秒!");
}else{
System.out.println(windowName + "沒有獲取到普通任務,正在空閒一秒");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//快速服務
public void expressService() {
String windowName = "第" + windowId + "號" + type + "窗口";
Integer serviceNumber = NumberMachine.getIntance().getExpressManager().fetchNumber();
System.out.println(windowName + "開始獲取快速服務!");
if(serviceNumber != null){
...
}else{
System.out.println(windowName + "沒有獲取到快速任務!");
commonService();
}
}
//vip服務
public void vipService() {
String windowName = "第" + windowId + "號" + type + "窗口";
Integer serviceNumber = NumberMachine.getIntance().getExpressManager().fetchNumber();
System.out.println(windowName + "開始獲取VIP服務!");
if(serviceNumber != null){
....
}else{
System.out.println(windowName + "沒有獲取到VIP任務!");
commonService();
}
}
}}
(5).Constants類(服務時間)
定義三個常量:MAX_SERVICE_TIME、MIN_SERVICE_TIME、COMMON_CUSTOMER_INTERVAL_TIME
public class Constants {
public static int MAX_SERVICE_TIME = 10000; //10秒!
public static int MIN_SERVICE_TIME = 1000; //1秒!
//平均產生用戶的時間間隔
public static int COMMON_CUSTOMER_INTERVAL_TIME = 1;
}
(6).MainClass類(主函數)
用for循環創建出4個普通窗口,再創建出1個快速窗口和一個VIP窗口。
接着再創建三個定時器,分別定時去創建新的普通客戶號碼、新的快速客戶號碼、新的VIP客戶號碼。
部分代碼:
public class MainClass {
public static void main(String[] args) {
//產生四個普通窗口
for(int i=1;i<5;i++){
ServiceWindow commonWindow = new ServiceWindow();
commonWindow.setWindowId(i);
commonWindow.start();
}
//產生一個快速窗口
.....//與普通窗口類似
//產生一個vip窗口
..... //與普通窗口類似
//普通客戶拿號
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable(){
public void run(){
Integer serviceNumber = NumberMachine.getIntance().getCommonManager().generateNewNumber();
System.out.println("第" + serviceNumber +"個客戶正在等待服務!");
}
},
0,
Constants.COMMON_CUSTOMER_INTERVAL_TIME,
TimeUnit.SECONDS);
//快速客戶拿號
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
....
Constants.COMMON_CUSTOMER_INTERVAL_TIME * 2
....
}
//VIP客戶拿號
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
.....
Constants.COMMON_CUSTOMER_INTERVAL_TIME * 6
.....
}
}
銀行業務調度系統比交通燈稍微難一些,主要是對象的確定以及對象之間的關係,期間還用到了多線程、線程池和計時器等等,這是看完張孝祥老師的視頻後的學習總結,實現了業務邏輯,但還不完善,繼續練習。
---------------------- android培訓、java培訓、期待與您交流! ----------------------詳細請查看:http://edu.csdn.net/heima