银行取号叫号业务系统调度的简单实现
今天看到一个比较好玩的需求,模拟实现银行业务调度系统逻辑,需求如下:
银行业务调度系统 模拟实现银行业务调度系统逻辑,具体需求如下: 银行内有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号普通客户服务