銀行取號叫號業務系統調度的簡單實現


今天看到一個比較好玩的需求,模擬實現銀行業務調度系統邏輯,需求如下:

銀行業務調度系統

模擬實現銀行業務調度系統邏輯,具體需求如下:

    銀行內有6個業務窗口,1 - 4號窗口為普通窗口,5號窗口為快速窗口,6號窗口為VIP窗口。

    有三種對應類型的客戶:VIP客戶,普通客戶,快速客戶(辦理如交水電費、電話費之類業務的客戶)。

    異步隨機生成各種類型的客戶,生成各類型用戶的概率比例為:

        VIP客戶 :普通客戶 :快速客戶  =  1 :6 :3。

    客戶辦理業務所需時間有最大值和最小值,在該范圍內隨機設定每個VIP客戶以及普通客戶辦理業務所需的時間,快速客戶辦理業務所需時間為最小值(提示:辦理業務的過程可通過線程Sleep的方式模擬)。

    各類型客戶在其對應窗口按順序依次辦理業務。 

    當VIP(6號)窗口和快速業務(5號)窗口沒有客戶等待辦理業務的時候,這兩個窗口可以處理普通客戶的業務,而一旦有對應的客戶等待辦理業務的時候,則優先處理對應客戶的業務。

    隨機生成客戶時間間隔以及業務辦理時間最大值和最小值自定,可以設置。

    不要求實現GUI,只考慮系統邏輯實現,可通過Log方式展現程序運行結果。

 

NumberManager類:

 定義一個用於存儲上一個客戶號碼的成員變量和用於存儲所有等待服務的客戶號碼的隊列集合。

定義一個產生新號碼的方法和獲取馬上要為之服務的號碼的方法,這兩個方法被不同的線程操作了相同的數據,所以要進行同步。代碼如下:

 1 package com.isoftstone.bank;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 
 7 /**
 8  * 管理號碼的類,用於存儲上一個客戶的成員變量和用於存儲所有等待服務的客戶號碼的隊列集合
 9  */
10 public class NumberManager {
11     //上一個客戶的號碼
12     private int lastNumber=0;
13     //等待服務的客戶號碼集合
14     private List quenueNumbers = new ArrayList();
15     
16     //產生新號碼的方法
17     public synchronized Integer generateNewNumber() {
18         quenueNumbers.add(++lastNumber);
19         return lastNumber;
20     }
21     
22     //獲取馬上要為之服務的號碼
23     public synchronized Integer fetchNumber() {
24         if(quenueNumbers.size() > 0) {
25             return (Integer) quenueNumbers.remove(0);
26         }else{
27             return null;
28         }
29         
30     }
31 }

NumberMachine類:

定義3個成員變量分別指向3個NumberManager對象,分別表示普通,快速和VIP的號碼管理器,定義3個對應的方法來返回這3個NumberManager對象。

將NumberMachine類設計成單例。

 1 package com.isoftstone.bank;
 2 
 3 //生成號碼的類
 4 public class NumberMachine {
 5     //提供空參構造
 6     private NumberMachine() {}
 7     //將NumberMachine設計成單例模式
 8     private static NumberMachine instance = new NumberMachine();
 9     public static NumberMachine getInstance() {
10         return instance;
11         
12     }
13     
14     //普通客戶的號碼管理器
15     private NumberManager commonManager = new NumberManager();
16     //快速辦理的客戶號碼管理器
17     private NumberManager expressManager = new NumberManager();
18     //vip客戶的號碼管理器
19     private NumberManager vipManager = new NumberManager();
20     public NumberManager getCommonManager() {
21         return commonManager;
22     }
23     public NumberManager getExpressManager() {
24         return expressManager;
25     }
26     public NumberManager getVipManager() {
27         return vipManager;
28     }
29     
30 }

CustomerType枚舉類:

系統有3類型的客戶,所以定義一個枚舉類,其中定義3個成員分別表示3中類型的客戶。

重寫toString方法,返回類型的中文名稱。

 

 1 package com.isoftstone.bank;
 2 
 3 //客戶類型
 4 public enum CustomerType {
 5     COMMON,EXPRESS,VIP;
 6     
 7     //重寫toString的方法
 8     public String toString() {
 9         String name = null;
10         switch(this) {
11         case COMMON:
12             name = "普通";
13             break;
14         case EXPRESS:
15             name = "快速";
16             break;
17         case VIP:
18             name = name();
19             break;
20         }
21         
22         return name;
23     }
24 }

ServiceWindow類

定義一個start方法,內部啟動一個線程,根據服務窗口的類別分別循環調用3個不同的方法。

定義3個方法分別對3中客戶進行服務

  1 package com.isoftstone.bank;
  2 
  3 import java.util.Random;
  4 import java.util.concurrent.Executors;
  5 import java.util.logging.Logger;
  6 
  7 public class ServiceWindow {
  8 
  9     private static Logger logger = Logger.getLogger("com.isoftstone.bank");
 10     private CustomerType type = CustomerType.COMMON;
 11     private int number = 1;
 12 
 13     public CustomerType getType() {
 14         return type;
 15     }
 16 
 17     public void setType(CustomerType type) {
 18         this.type = type;
 19     }
 20 
 21     public void setNumber(int number) {
 22         this.number = number;
 23     }
 24 
 25     public void start() {
 26         Executors.newSingleThreadExecutor().execute(new Runnable() {
 27             public void run() {
 28                 while (true) {
 29                     switch (type) {
 30                     case COMMON:
 31                         commonService();
 32                         break;
 33                     case EXPRESS:
 34                         expressService();
 35                         break;
 36                     case VIP:
 37                         vipService();
 38                         break;
 39                     }
 40                 }
 41             }
 42 
 43             private void vipService() {
 44                 Integer serviceNumber = NumberMachine.getInstance().getVipManager().fetchNumber();
 45                 String windowName = "第" + number + "號" + type + "窗口";
 46                 System.out.println(windowName + "開始獲取VIP任務!");
 47                 if (serviceNumber != null) {
 48                     System.out.println(windowName + "開始為第" + serviceNumber + "號VIP客戶服務");
 49                     int maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
 50                     int serviceTime = new Random().nextInt(maxRandom) + 1 + Constants.MIN_SERVICE_TIME;
 51                     try {
 52                         Thread.sleep(serviceTime);
 53                     } catch (InterruptedException e) {
 54                         e.printStackTrace();
 55                     }
 56                     System.out
 57                             .println(windowName + "完成為第" + serviceNumber + "號VIP客戶服務,總共耗時" + serviceTime / 1000 + "秒");
 58                 } else {
 59                     System.out.println(windowName + "沒有取到VIP任務!");
 60                     commonService();
 61                 }
 62 
 63             }
 64 
 65             private void expressService() {
 66                 Integer serviceNumber = NumberMachine.getInstance().getExpressManager().fetchNumber();
 67                 String windowName = "第" + number + "號" + type + "窗口";
 68                 System.out.println(windowName + "開始獲取快速任務!");
 69                 if (serviceNumber != null) {
 70                     System.out.println(windowName + "開始為第" + serviceNumber + "號快速客戶服務");
 71                     int serviceTime = Constants.MIN_SERVICE_TIME;
 72                     try {
 73                         Thread.sleep(serviceTime);
 74                     } catch (InterruptedException e) {
 75                         e.printStackTrace();
 76                     }
 77                     System.out.println(windowName + "完成為第" + serviceNumber + "號快速客戶服務,總共耗時" + serviceTime / 1000 + "秒");
 78                 } else {
 79                     System.out.println(windowName + "沒有取到快速任務!");
 80                     commonService();
 81                 }
 82             }
 83 
 84             private void commonService() {
 85                 String windowName = "第" + number + "號" + type + "窗口";
 86                 System.out.println(windowName + "開始獲取普通任務!");
 87                 Integer serviceNumber = NumberMachine.getInstance().getCommonManager().fetchNumber();
 88                 if (serviceNumber != null) {
 89                     System.out.println(windowName + "開始為第" + serviceNumber + "號普通客戶服務");
 90                     int maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
 91                     int serviceTime = new Random().nextInt(maxRandom) + 1 + Constants.MIN_SERVICE_TIME;
 92 
 93                     try {
 94                         Thread.sleep(serviceTime);
 95                     } catch (InterruptedException e) {
 96                         e.printStackTrace();
 97                     }
 98                     System.out.println(windowName + "完成為第" + serviceNumber + "號普通客戶服務,總共耗時" + serviceTime / 1000 + "秒");
 99                 } else {
100                     System.out.println(windowName + "沒有取到普通任務,正在空閑一秒");
101                     try {
102                         Thread.sleep(1000);
103                     } catch (InterruptedException e) {
104                         e.printStackTrace();
105                     }
106                 }
107             }
108         });
109     }
110 }

MainClass類

用for循環創建出4個普通窗口,再創建出一個快速窗口和一個vip窗口。創建3個定時器,分別定時去創建新的普通客戶號碼,新的快速客戶號碼,新的vip客戶號碼。

 1 package com.isoftstone.bank;
 2 
 3 import java.util.concurrent.Executors;
 4 import java.util.concurrent.TimeUnit;
 5 import java.util.logging.Logger;
 6 
 7 public class MainClass {
 8     
 9     private static Logger logger = Logger.getLogger("com.isoftstone.bank");
10 
11     public static void main(String[] args) {
12         //產生4個普通窗口
13         for(int i = 1; i < 5; i++) {
14             ServiceWindow window = new ServiceWindow();
15             window.setNumber(i);
16             window.start();
17         }
18         
19         //產生1個快速窗口
20         ServiceWindow expressWindow = new ServiceWindow();
21         expressWindow.setType(CustomerType.EXPRESS);
22         expressWindow.start();
23         
24         //產生一個vip窗口
25         ServiceWindow vipWindow = new ServiceWindow();
26         vipWindow.setType(CustomerType.VIP);
27         vipWindow.start();
28         
29         //普通客戶拿號
30                 Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
31                         new Runnable(){
32                             public void run(){
33                                 Integer serviceNumber = NumberMachine.getInstance().getCommonManager().generateNewNumber();
34                                 /**
35                                  * 采用logger方式,無法看到直觀的運行效果,因為logger.log方法內部並不是直接把內容打印出出來,
36                                  * 而是交給內部的一個線程去處理,所以,打印出來的結果在時間順序上看起來很混亂。
37                                  */
38                                 //logger.info("第" + serviceNumber + "號普通客戶正在等待服務!");
39                                 System.out.println("第" + serviceNumber + "號普通客戶正在等待服務!");                        
40                             }
41                         },
42                         0,
43                         Constants.COMMON_CUSTOMER_INTERVAL_TIME, 
44                         TimeUnit.SECONDS);
45                 
46                 //快速客戶拿號
47                 Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
48                         new Runnable(){
49                             public void run(){
50                                 Integer serviceNumber = NumberMachine.getInstance().getExpressManager().generateNewNumber();
51                                 System.out.println("第" + serviceNumber + "號快速客戶正在等待服務!");
52                             }
53                         },
54                         0,
55                         Constants.COMMON_CUSTOMER_INTERVAL_TIME * 2, 
56                         TimeUnit.SECONDS);
57                 
58                 //VIP客戶拿號
59                 Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
60                         new Runnable(){
61                             public void run(){
62                                 Integer serviceNumber = NumberMachine.getInstance().getVipManager().generateNewNumber();
63                                 System.out.println("第" + serviceNumber + "號VIP客戶正在等待服務!");
64                             }
65                         },
66                         0,
67                         Constants.COMMON_CUSTOMER_INTERVAL_TIME * 6, 
68                         TimeUnit.SECONDS);
69             
70     }
71 }

Constants類

定義3個常量:MAX_SERVICE_TIME, MIN_SERVICE_TIME,COMMON_CUSTOMER_INTERVAL_TIME

 1 package com.isoftstone.bank;
 2 
 3 public class Constants {
 4     //最長辦理時間為10秒
 5     public static int MAX_SERVICE_TIME = 10000;
 6     //最短辦理時間為1秒
 7     public static int MIN_SERVICE_TIME = 1000;
 8     //一秒鍾產生一個普通用戶
 9     public static int COMMON_CUSTOMER_INTERVAL_TIME = 1;
10 }

運行結果如下:

第1號普通窗口開始獲取普通任務!
第3號普通窗口開始獲取普通任務!
第2號普通窗口開始獲取普通任務!
第4號普通窗口開始獲取普通任務!
第1號普通窗口沒有取到普通任務,正在空閑一秒
第4號普通窗口沒有取到普通任務,正在空閑一秒
第1號VIP窗口開始獲取VIP任務!
第1號VIP窗口沒有取到VIP任務!
第1號快速窗口開始獲取快速任務!
第2號普通窗口沒有取到普通任務,正在空閑一秒
第3號普通窗口沒有取到普通任務,正在空閑一秒
第1號快速窗口沒有取到快速任務!
第1號VIP窗口開始獲取普通任務!
第1號VIP窗口沒有取到普通任務,正在空閑一秒
第1號快速窗口開始獲取普通任務!
第1號快速窗口沒有取到普通任務,正在空閑一秒
第1號普通客戶正在等待服務!
第1號快速客戶正在等待服務!
第1號VIP客戶正在等待服務!
第4號普通窗口開始獲取普通任務!
第1號普通窗口開始獲取普通任務!
第1號普通窗口沒有取到普通任務,正在空閑一秒
第4號普通窗口開始為第1號普通客戶服務
第3號普通窗口開始獲取普通任務!
第3號普通窗口沒有取到普通任務,正在空閑一秒
第2號普通窗口開始獲取普通任務!
第2號普通窗口沒有取到普通任務,正在空閑一秒
第1號快速窗口開始獲取快速任務!
第1號VIP窗口開始獲取VIP任務!
第1號快速窗口開始為第1號快速客戶服務
第1號VIP窗口開始為第1號VIP客戶服務
第2號普通客戶正在等待服務!
第1號普通窗口開始獲取普通任務!
第1號普通窗口開始為第2號普通客戶服務
第3號普通窗口開始獲取普通任務!
第3號普通窗口沒有取到普通任務,正在空閑一秒
第2號普通窗口開始獲取普通任務!
第2號普通窗口沒有取到普通任務,正在空閑一秒
第1號快速窗口完成為第1號快速客戶服務,總共耗時1秒
第1號快速窗口開始獲取快速任務!
第1號快速窗口沒有取到快速任務!
第1號快速窗口開始獲取普通任務!
第1號快速窗口沒有取到普通任務,正在空閑一秒
第3號普通客戶正在等待服務!
第2號快速客戶正在等待服務!
第1號VIP窗口完成為第1號VIP客戶服務,總共耗時1秒
第1號VIP窗口開始獲取VIP任務!
第1號VIP窗口沒有取到VIP任務!
第1號VIP窗口開始獲取普通任務!
第1號VIP窗口開始為第3號普通客戶服務
第3號普通窗口開始獲取普通任務!
第3號普通窗口沒有取到普通任務,正在空閑一秒
第2號普通窗口開始獲取普通任務!
第2號普通窗口沒有取到普通任務,正在空閑一秒
第1號快速窗口開始獲取快速任務!
第1號快速窗口開始為第2號快速客戶服務
第4號普通客戶正在等待服務!
第3號普通窗口開始獲取普通任務!
第2號普通窗口開始獲取普通任務!
第2號普通窗口沒有取到普通任務,正在空閑一秒
第3號普通窗口開始為第4號普通客戶服務
第1號快速窗口完成為第2號快速客戶服務,總共耗時1秒
第1號快速窗口開始獲取快速任務!
第1號快速窗口沒有取到快速任務!
第1號快速窗口開始獲取普通任務!
第1號快速窗口沒有取到普通任務,正在空閑一秒
第5號普通客戶正在等待服務!
第3號快速客戶正在等待服務!
第2號普通窗口開始獲取普通任務!
第2號普通窗口開始為第5號普通客戶服務
第1號快速窗口開始獲取快速任務!
第1號快速窗口開始為第3號快速客戶服務
第6號普通客戶正在等待服務!
第1號快速窗口完成為第3號快速客戶服務,總共耗時1秒
第1號快速窗口開始獲取快速任務!
第1號快速窗口沒有取到快速任務!
第1號快速窗口開始獲取普通任務!
第1號快速窗口開始為第6號普通客戶服務
第7號普通客戶正在等待服務!
第4號快速客戶正在等待服務!
第2號VIP客戶正在等待服務!
第8號普通客戶正在等待服務!
第1號VIP窗口完成為第3號普通客戶服務,總共耗時5秒
第1號VIP窗口開始獲取VIP任務!
第1號VIP窗口開始為第2號VIP客戶服務
第9號普通客戶正在等待服務!
第5號快速客戶正在等待服務!
第10號普通客戶正在等待服務!
第2號普通窗口完成為第5號普通客戶服務,總共耗時4秒
第2號普通窗口開始獲取普通任務!
第2號普通窗口開始為第7號普通客戶服務
第4號普通窗口完成為第1號普通客戶服務,總共耗時8秒
第4號普通窗口開始獲取普通任務!
第4號普通窗口開始為第8號普通客戶服務
第11號普通客戶正在等待服務!
第6號快速客戶正在等待服務!
第1號普通窗口完成為第2號普通客戶服務,總共耗時8秒
第1號普通窗口開始獲取普通任務!
第1號普通窗口開始為第9號普通客戶服務
第12號普通客戶正在等待服務!
第13號普通客戶正在等待服務!
第7號快速客戶正在等待服務!
第3號VIP客戶正在等待服務!
第1號VIP窗口完成為第2號VIP客戶服務,總共耗時4秒
第1號VIP窗口開始獲取VIP任務!
第1號VIP窗口開始為第3號VIP客戶服務
第2號普通窗口完成為第7號普通客戶服務,總共耗時3秒
第2號普通窗口開始獲取普通任務!
第2號普通窗口開始為第10號普通客戶服務
第14號普通客戶正在等待服務!
第1號快速窗口完成為第6號普通客戶服務,總共耗時7秒
第1號快速窗口開始獲取快速任務!
第1號快速窗口開始為第4號快速客戶服務
第3號普通窗口完成為第4號普通客戶服務,總共耗時9秒
第3號普通窗口開始獲取普通任務!
第3號普通窗口開始為第11號普通客戶服務

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM