銀行調度
銀行調度,模擬了實際生活中的銀行對客戶服務的排隊管理系統。將現實中排隊管理,抽象為對象模型。 抽象出了一個號碼機,為每個客戶生產號碼標識,并形成一個先進先出的隊列,模擬了現實中的排隊。
將對客戶的服務,進行抽象,得出是由服務窗口進行叫號,而不是窗口服務員。
這個案例的核心,就是號碼管理機器,為每個客戶生成一個號碼,并排成先進先出隊列,模擬了實際生活。然后由 服務窗口,取隊列的號,進行服務,模擬了現實中的服務窗口。
1 //常量定義
2 public class Constants {
3 public static int MAX_SERVICE_TIME = 10000; //10秒!
4 public static int MIN_SERVICE_TIME = 1000; //1秒!
5
6 /*每個普通窗口服務一個客戶的平均時間為5秒,一共有4個這樣的窗口,也就是說銀行的所有普通窗口合起來
7 * 平均1.25秒內可以服務完一個普通客戶,再加上快速窗口和VIP窗口也可以服務普通客戶,所以,
8 * 1秒鐘產生一個普通客戶比較合理,*/
9 public static int COMMON_CUSTOMER_INTERVAL_TIME = 1;
10 }
11
2 public class Constants {
3 public static int MAX_SERVICE_TIME = 10000; //10秒!
4 public static int MIN_SERVICE_TIME = 1000; //1秒!
5
6 /*每個普通窗口服務一個客戶的平均時間為5秒,一共有4個這樣的窗口,也就是說銀行的所有普通窗口合起來
7 * 平均1.25秒內可以服務完一個普通客戶,再加上快速窗口和VIP窗口也可以服務普通客戶,所以,
8 * 1秒鐘產生一個普通客戶比較合理,*/
9 public static int COMMON_CUSTOMER_INTERVAL_TIME = 1;
10 }
11
1 //客戶類型
2 public enum CustomerType {
3 COMMON,EXPRESS,VIP;
4 public String toString(){
5 String name = null;
6 switch(this){
7 case COMMON:
8 name = "普通";
9 break;
10 case EXPRESS:
11 name = "快速";
12 break;
13 case VIP:
14 name = name();
15 break;
16 }
17 return name;
18 }
19 }
20
2 public enum CustomerType {
3 COMMON,EXPRESS,VIP;
4 public String toString(){
5 String name = null;
6 switch(this){
7 case COMMON:
8 name = "普通";
9 break;
10 case EXPRESS:
11 name = "快速";
12 break;
13 case VIP:
14 name = name();
15 break;
16 }
17 return name;
18 }
19 }
20
1 //號碼產生器
2 public class NumberMachine {
3
4 private NumberMachine(){}
5 private static NumberMachine instance = new NumberMachine();//單例此類
6 public static NumberMachine getInstance(){
7 return instance;
8 }
9
10 private NumberManager commonManager = new NumberManager(); //生產一個普通號
11 private NumberManager expressManager = new NumberManager(); //生產一個快速號
12 private NumberManager vipManager = new NumberManager(); //生產一個vip號
13 public NumberManager getCommonManager() {
14 return commonManager;
15 }
16 public NumberManager getExpressManager() {
17 return expressManager;
18 }
19 public NumberManager getVipManager() {
20 return vipManager;
21 }
22
23 }
2 public class NumberMachine {
3
4 private NumberMachine(){}
5 private static NumberMachine instance = new NumberMachine();//單例此類
6 public static NumberMachine getInstance(){
7 return instance;
8 }
9
10 private NumberManager commonManager = new NumberManager(); //生產一個普通號
11 private NumberManager expressManager = new NumberManager(); //生產一個快速號
12 private NumberManager vipManager = new NumberManager(); //生產一個vip號
13 public NumberManager getCommonManager() {
14 return commonManager;
15 }
16 public NumberManager getExpressManager() {
17 return expressManager;
18 }
19 public NumberManager getVipManager() {
20 return vipManager;
21 }
22
23 }
1 //取號機,每來一個客戶,生成一個號碼,插入到ArrayList
2 import java.util.ArrayList;
3 import java.util.List;
4
5 public class NumberManager {
6 private int lastNumber = 0;
7 private List queueNumbers = new ArrayList();
8
9 public synchronized Integer generateNewNumber(){
10 queueNumbers.add(++lastNumber);
11 return lastNumber;
12 }
13
14 public synchronized Integer fetchNumber(){
15 if(queueNumbers.size()>0){
16 return (Integer)queueNumbers.remove(0);
17 }else{
18 return null;
19 }
20 }
21 }
22
2 import java.util.ArrayList;
3 import java.util.List;
4
5 public class NumberManager {
6 private int lastNumber = 0;
7 private List queueNumbers = new ArrayList();
8
9 public synchronized Integer generateNewNumber(){
10 queueNumbers.add(++lastNumber);
11 return lastNumber;
12 }
13
14 public synchronized Integer fetchNumber(){
15 if(queueNumbers.size()>0){
16 return (Integer)queueNumbers.remove(0);
17 }else{
18 return null;
19 }
20 }
21 }
22
1 //服務窗口,進行叫號,根據客戶類型,調用相應的服務類型
2 import java.util.Random;
3 import java.util.concurrent.Executors;
4 import java.util.logging.Logger;
5
6 /**
7 * 沒有把VIP窗口和快速窗口做成子類,是因為實際業務中的普通窗口可以隨時被設置為VIP窗口和快速窗口。
8 * */
9 public class ServiceWindow {
10 private static Logger logger = Logger.getLogger("cn.itcast.bankqueue");
11 private CustomerType type = CustomerType.COMMON;
12 private int number = 1;
13
14 public CustomerType getType() {
15 return type;
16 }
17
18 public void setType(CustomerType type) {
19 this.type = type;
20 }
21
22 public void setNumber(int number){
23 this.number = number;
24 }
25
26 public void start(){
27 Executors.newSingleThreadExecutor().execute(
28 new Runnable(){
29 public void run(){
30 //下面這種寫法的運行效率低,最好是把while放在case下面
31 while(true){
32 switch(type){
33 case COMMON:
34 commonService();
35 break;
36 case EXPRESS:
37 expressService();
38 break;
39 case VIP:
40 vipService();
41 break;
42 }
43 }
44 }
45 }
46 );
47 }
48
49 private void commonService(){
50 String windowName = "第" + number + "號" + type + "窗口";
51 System.out.println(windowName + "開始獲取普通任務!");
52 Integer serviceNumber = NumberMachine.getInstance().getCommonManager().fetchNumber();
53 if(serviceNumber != null ){
54 System.out.println(windowName + "開始為第" + serviceNumber + "號普通客戶服務");
55 int maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
56 int serviceTime = new Random().nextInt(maxRandom)+1 + Constants.MIN_SERVICE_TIME;
57
58 try {
59 Thread.sleep(serviceTime);
60 } catch (InterruptedException e) {
61 e.printStackTrace();
62 }
63 System.out.println(windowName + "完成為第" + serviceNumber + "號普通客戶服務,總共耗時" + serviceTime/1000 + "秒");
64 }else{
65 System.out.println(windowName + "沒有取到普通任務,正在空閑一秒");
66 try {
67 Thread.sleep(1000);
68 } catch (InterruptedException e) {
69 e.printStackTrace();
70 }
71 }
72 }
73
74 private void expressService(){
75 Integer serviceNumber = NumberMachine.getInstance().getExpressManager().fetchNumber();
76 String windowName = "第" + number + "號" + type + "窗口";
77 System.out.println(windowName + "開始獲取快速任務!");
78 if(serviceNumber !=null){
79 System.out.println(windowName + "開始為第" + serviceNumber + "號快速客戶服務");
80 int serviceTime = Constants.MIN_SERVICE_TIME;
81 try {
82 Thread.sleep(serviceTime);
83 } catch (InterruptedException e) {
84 e.printStackTrace();
85 }
86 System.out.println(windowName + "完成為第" + serviceNumber + "號快速客戶服務,總共耗時" + serviceTime/1000 + "秒");
87 }else{
88 System.out.println(windowName + "沒有取到快速任務!");
89 commonService();
90 }
91 }
92
93 private void vipService(){
94
95 Integer serviceNumber = NumberMachine.getInstance().getVipManager().fetchNumber();
96 String windowName = "第" + number + "號" + type + "窗口";
97 System.out.println(windowName + "開始獲取VIP任務!");
98 if(serviceNumber !=null){
99 System.out.println(windowName + "開始為第" + serviceNumber + "號VIP客戶服務");
100 int maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
101 int serviceTime = new Random().nextInt(maxRandom)+1 + Constants.MIN_SERVICE_TIME;
102 try {
103 Thread.sleep(serviceTime);
104 } catch (InterruptedException e) {
105 e.printStackTrace();
106 }
107 System.out.println(windowName + "完成為第" + serviceNumber + "號VIP客戶服務,總共耗時" + serviceTime/1000 + "秒");
108 }else{
109 System.out.println(windowName + "沒有取到VIP任務!");
110 commonService();
111 }
112 }
113 }
114
2 import java.util.Random;
3 import java.util.concurrent.Executors;
4 import java.util.logging.Logger;
5
6 /**
7 * 沒有把VIP窗口和快速窗口做成子類,是因為實際業務中的普通窗口可以隨時被設置為VIP窗口和快速窗口。
8 * */
9 public class ServiceWindow {
10 private static Logger logger = Logger.getLogger("cn.itcast.bankqueue");
11 private CustomerType type = CustomerType.COMMON;
12 private int number = 1;
13
14 public CustomerType getType() {
15 return type;
16 }
17
18 public void setType(CustomerType type) {
19 this.type = type;
20 }
21
22 public void setNumber(int number){
23 this.number = number;
24 }
25
26 public void start(){
27 Executors.newSingleThreadExecutor().execute(
28 new Runnable(){
29 public void run(){
30 //下面這種寫法的運行效率低,最好是把while放在case下面
31 while(true){
32 switch(type){
33 case COMMON:
34 commonService();
35 break;
36 case EXPRESS:
37 expressService();
38 break;
39 case VIP:
40 vipService();
41 break;
42 }
43 }
44 }
45 }
46 );
47 }
48
49 private void commonService(){
50 String windowName = "第" + number + "號" + type + "窗口";
51 System.out.println(windowName + "開始獲取普通任務!");
52 Integer serviceNumber = NumberMachine.getInstance().getCommonManager().fetchNumber();
53 if(serviceNumber != null ){
54 System.out.println(windowName + "開始為第" + serviceNumber + "號普通客戶服務");
55 int maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
56 int serviceTime = new Random().nextInt(maxRandom)+1 + Constants.MIN_SERVICE_TIME;
57
58 try {
59 Thread.sleep(serviceTime);
60 } catch (InterruptedException e) {
61 e.printStackTrace();
62 }
63 System.out.println(windowName + "完成為第" + serviceNumber + "號普通客戶服務,總共耗時" + serviceTime/1000 + "秒");
64 }else{
65 System.out.println(windowName + "沒有取到普通任務,正在空閑一秒");
66 try {
67 Thread.sleep(1000);
68 } catch (InterruptedException e) {
69 e.printStackTrace();
70 }
71 }
72 }
73
74 private void expressService(){
75 Integer serviceNumber = NumberMachine.getInstance().getExpressManager().fetchNumber();
76 String windowName = "第" + number + "號" + type + "窗口";
77 System.out.println(windowName + "開始獲取快速任務!");
78 if(serviceNumber !=null){
79 System.out.println(windowName + "開始為第" + serviceNumber + "號快速客戶服務");
80 int serviceTime = Constants.MIN_SERVICE_TIME;
81 try {
82 Thread.sleep(serviceTime);
83 } catch (InterruptedException e) {
84 e.printStackTrace();
85 }
86 System.out.println(windowName + "完成為第" + serviceNumber + "號快速客戶服務,總共耗時" + serviceTime/1000 + "秒");
87 }else{
88 System.out.println(windowName + "沒有取到快速任務!");
89 commonService();
90 }
91 }
92
93 private void vipService(){
94
95 Integer serviceNumber = NumberMachine.getInstance().getVipManager().fetchNumber();
96 String windowName = "第" + number + "號" + type + "窗口";
97 System.out.println(windowName + "開始獲取VIP任務!");
98 if(serviceNumber !=null){
99 System.out.println(windowName + "開始為第" + serviceNumber + "號VIP客戶服務");
100 int maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
101 int serviceTime = new Random().nextInt(maxRandom)+1 + Constants.MIN_SERVICE_TIME;
102 try {
103 Thread.sleep(serviceTime);
104 } catch (InterruptedException e) {
105 e.printStackTrace();
106 }
107 System.out.println(windowName + "完成為第" + serviceNumber + "號VIP客戶服務,總共耗時" + serviceTime/1000 + "秒");
108 }else{
109 System.out.println(windowName + "沒有取到VIP任務!");
110 commonService();
111 }
112 }
113 }
114
1 //主類,生成服務窗口,進行叫號,根據叫號時間間隔,達到1:6:3 的客戶比例
2 import java.util.concurrent.Executors;
3 import java.util.concurrent.TimeUnit;
4 import java.util.logging.Logger;
5
6 public class MainClass {
7
8 private static Logger logger = Logger.getLogger("cn.itcast.bankqueue");
9
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 //產生1個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 }
2 import java.util.concurrent.Executors;
3 import java.util.concurrent.TimeUnit;
4 import java.util.logging.Logger;
5
6 public class MainClass {
7
8 private static Logger logger = Logger.getLogger("cn.itcast.bankqueue");
9
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 //產生1個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 }
posted on 2011-01-11 10:45 杰點 閱讀(200) 評論(0) 編輯 收藏 所屬分類: JAVA