1.系统的逻辑的业务需求分析
模拟实现银行业务调度系统逻辑,具体需求如下: 银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。 有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。 异步随机生成各种类型的客户,生成各类型用户的概率比例为: VIP客户 :普通客户 :快速客户 = 1 :6 :3。 客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需的时间,快速客户办理业务所需时间为最小值(提示:办理业务的过程可通过线程Sleep的方式模拟)。 各类型客户在其对应窗口按顺序依次办理业务。 当VIP(6号)窗口和快速业务(5号)窗口没有客户等待办理业务的时候,这两个窗口可以处理普通客户的业务,而一旦有对应的客户等待办理业务的时候,则优先处理对应客户的业务。 随机生成客户时间间隔以及业务办理时间最大值和最小值自定,可以设置。 不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。
2.系统面向对象设计
系统类图:
3.系统相关类的设计及测试
NumberManager.java
package com.itcast.interview.bank;import java.util.ArrayList;import java.util.List;/** * 号码管理器类 * 定义一个用于存储上一个客户号码的成员变量和用于存储所有等待服务的客户号码的队列集合. * 定义一个产生新号码的方法和获取马上要为之服务的号码的方法, * 这两个方法被不同的线程操作了相同的数据,所以,要进行同步. */public class NumberManager{ /*生成器的最后的号码*/ private int lastNumber; /*将要服务的号码放入队列*/ private ListserviceList=new ArrayList (); /*生成器提供服务号码*/ public synchronized Integer generateNumber(){ lastNumber++; serviceList.add(lastNumber); return lastNumber; } /*服务窗口取服务号码*/ public synchronized Integer fetchServiceNumber(){ if(serviceList.size()>0){ return serviceList.remove(0); }else{ return null; } }}
NumberMachine.java
package com.itcast.interview.bank;/** * 号码机器(管理三个号码管理器) * 定义三个成员变量分别指向三个NumberManager对象, * 分别表示普通、快速和VIP客户的号码管理器, * 定义三个对应的方法来返回这三个NumberManager对象。 * 将NumberMachine类设计成单例。 */public class NumberMachine { 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; } private NumberMachine(){} private static NumberMachine instance=new NumberMachine(); public static NumberMachine getInstance(){ return instance; }}
ServiceWindow.java
package com.itcast.interview.bank;import java.util.Random;import java.util.concurrent.Executors;/** * 定义一个start方法,内部启动一个线程,根据服务窗口的类别分别循环调用三个不同的方法。 * 定义三个方法分别对三种客户进行服务,为了观察运行效果,应详细打印出其中的细节信息. */public class ServiceWindow { private CustomerType serviceType=CustomerType.COMMON; private Integer windowId=1; public void setServiceType(CustomerType serviceType) { this.serviceType = serviceType; } public void setWindowId(Integer windowId) { this.windowId = windowId; } public void start(){ Executors.newSingleThreadExecutor().execute(new Runnable() { @Override public void run(){ while(true){ switch(serviceType){ case COMMON: commonService(); break; case EXPRESS: expressService(); break; case VIP: vipService(); break; } } } });; } private void commonService() { String windowName="第"+windowId+"号"+serviceType+"窗口"; Integer serviceNumber=NumberMachine.getInstance().getCommonManager().fetchServiceNumber(); System.out.println(windowName+"正在获取普通服务号码"); if(serviceNumber!=null){ System.out.println(windowName + "开始为第" + serviceNumber + "号普通客户服务"); int maxRandom=Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME; /*服务时间*/ long serverTime=(new Random().nextInt(maxRandom)+1)+Constants.MIN_SERVICE_TIME; try { Thread.sleep(serverTime); } catch (InterruptedException e) { e.printStackTrace(); } /*完成耗费总时间*/ long costTime=serverTime/1000; System.out.println(windowName+"为第"+serviceNumber+"个"+serviceType+"客户完成服务耗费的时间:"+costTime+"秒"); }else{ System.out.println(windowName+"没有取到普通服务号码"); System.out.println("休息一下"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } private void expressService() { String windowName="第"+windowId+"号"+serviceType+"窗口"; Integer serviceNumber=NumberMachine.getInstance().getExpressManager().fetchServiceNumber(); System.out.println(windowName+"正在获取快速服务号码"); if(serviceNumber!=null){ System.out.println(windowName + "开始为第" + serviceNumber + "号快速客户服务"); int serviceTime = Constants.MIN_SERVICE_TIME; try { Thread.sleep(serviceTime); } catch (InterruptedException e) { e.printStackTrace(); } long costTime=serviceTime/1000; System.out.println(windowName+"为第"+serviceNumber+"个"+serviceType+"客户完成服务耗费的时间:"+costTime+"秒"); }else{ System.out.println(windowName+"没有取到快速服务号码"); commonService(); } } private void vipService() { String windowName="第"+windowId+"号"+serviceType+"窗口"; Integer serviceNumber=NumberMachine.getInstance().getCommonManager().fetchServiceNumber(); System.out.println(windowName+"正在获取VIP服务号码"); if(serviceNumber!=null){ System.out.println(windowName + "开始为第" + serviceNumber + "号VIP客户服务"); int maxRandom=Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME; long serverTime=(new Random().nextInt(maxRandom)+1)+Constants.MIN_SERVICE_TIME; try { Thread.sleep(serverTime); } catch (InterruptedException e) { e.printStackTrace(); } long costTime=serverTime/1000; System.out.println(windowName+"为第"+serviceNumber+"个"+serviceType+"客户完成服务耗费的时间:"+costTime+"秒"); }else{ System.out.println(windowName+"没有取到VIP服务号码"); commonService(); } }}
CustomerType.java
package com.itcast.interview.bank;public enum CustomerType { COMMON,EXPRESS,VIP; public String toString(){ switch (this) { case COMMON: return "普通"; case EXPRESS: return "快速"; case VIP: return "VIP"; } return null; }}
Constants.java
package com.itcast.interview.bank;public class Constants { /*每个普通窗口服务一个客户的平均时间为5秒,一共有4个这样的窗口,也就是说银行的所有普通窗口合起来 * 平均1.25秒内可以服务完一个普通客户,再加上快速窗口和VIP窗口也可以服务普通客户,所以, * 1秒钟产生一个普通客户比较合理,*/ public static final long COMMON_CUSTOMER_INTERVAL_TIME = 1; public static final int MAX_SERVICE_TIME=10000; public static final int MIN_SERVICE_TIME=1000;}
Test.java
package com.itcast.interview.bank;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;public class Test { public static void main(String[] args) { // 产生4个普通窗口 for (int i = 1; i < 5; i++) { ServiceWindow window = new ServiceWindow(); window.setWindowId(i); window.start(); } // 产生1个快速窗口 ServiceWindow expressWindow = new ServiceWindow(); expressWindow.setServiceType(CustomerType.EXPRESS); expressWindow.start(); // 产生1个VIP窗口 ServiceWindow vipWindow = new ServiceWindow(); vipWindow.setServiceType(CustomerType.VIP); vipWindow.start(); // 普通客户拿号 Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() { public void run() { Integer serviceNumber = NumberMachine.getInstance() .getCommonManager().generateNumber(); System.out.println("第" + serviceNumber + "号普通客户正在等待服务!"); } }, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME, TimeUnit.SECONDS); // 快速客户拿号 Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() { public void run() { Integer serviceNumber = NumberMachine.getInstance() .getExpressManager().generateNumber(); System.out.println("第" + serviceNumber + "号快速客户正在等待服务!"); } }, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME * 2, TimeUnit.SECONDS); // VIP客户拿号 Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() { public void run() { Integer serviceNumber = NumberMachine.getInstance() .getVipManager().generateNumber(); System.out.println("第" + serviceNumber + "号VIP客户正在等待服务!"); } }, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME * 6, TimeUnit.SECONDS); }}
测试结果及分析
第1号普通窗口正在获取普通服务号码第1号普通窗口没有取到普通服务号码休息一下 --------//没有获取服务号码,休息一下第2号普通窗口正在获取普通服务号码第2号普通窗口没有取到普通服务号码休息一下第4号普通窗口正在获取普通服务号码第4号普通窗口没有取到普通服务号码休息一下第1号VIP窗口正在获取VIP服务号码第1号VIP窗口没有取到VIP服务号码第1号VIP窗口正在获取普通服务号码第1号VIP窗口没有取到普通服务号码 -----//VIP窗口没有任务时,可以获取普通服务号码.休息一下第1号快速客户正在等待服务!第1号普通客户正在等待服务!第3号普通窗口正在获取普通服务号码第1号快速窗口正在获取快速服务号码第1号快速窗口开始为第1号快速客户服务 -----//快速窗口开始服务第3号普通窗口没有取到普通服务号码休息一下第1号VIP客户正在等待服务!第1号普通窗口正在获取普通服务号码第1号普通窗口开始为第1号普通客户服务 -----//一号普通窗口先开始服务第2号普通窗口正在获取普通服务号码第2号普通窗口没有取到普通服务号码休息一下第4号普通窗口正在获取普通服务号码第4号普通窗口没有取到普通服务号码休息一下第2号普通客户正在等待服务!第1号VIP窗口正在获取VIP服务号码第1号VIP窗口开始为第2号VIP客户服务第3号普通窗口正在获取普通服务号码第3号普通窗口没有取到普通服务号码休息一下第1号快速窗口为第1个快速客户完成服务耗费的时间:1秒 ----//快速窗口服务结束第1号快速窗口正在获取快速服务号码第1号快速窗口没有取到快速服务号码第1号快速窗口正在获取普通服务号码第1号快速窗口没有取到普通服务号码休息一下第2号普通窗口正在获取普通服务号码第2号普通窗口没有取到普通服务号码休息一下第4号普通窗口正在获取普通服务号码第4号普通窗口没有取到普通服务号码休息一下第3号普通客户正在等待服务!第2号快速客户正在等待服务!第3号普通窗口正在获取普通服务号码第3号普通窗口开始为第3号普通客户服务第1号快速窗口正在获取快速服务号码第1号快速窗口开始为第2号快速客户服务第1号VIP窗口为第2个VIP客户完成服务耗费的时间:1秒第1号VIP窗口正在获取VIP服务号码第1号VIP窗口没有取到VIP服务号码第1号VIP窗口正在获取普通服务号码第1号VIP窗口没有取到普通服务号码休息一下第2号普通窗口正在获取普通服务号码第2号普通窗口没有取到普通服务号码休息一下第4号普通窗口正在获取普通服务号码第4号普通窗口没有取到普通服务号码休息一下第4号普通客户正在等待服务!第1号快速窗口为第2个快速客户完成服务耗费的时间:1秒 第1号快速窗口正在获取快速服务号码第1号快速窗口没有取到快速服务号码第1号快速窗口正在获取普通服务号码第1号快速窗口开始为第4号普通客户服务第1号VIP窗口正在获取VIP服务号码第1号VIP窗口没有取到VIP服务号码第1号VIP窗口正在获取普通服务号码第1号VIP窗口没有取到普通服务号码休息一下第2号普通窗口正在获取普通服务号码第2号普通窗口没有取到普通服务号码休息一下第4号普通窗口正在获取普通服务号码第4号普通窗口没有取到普通服务号码休息一下第3号快速客户正在等待服务!第5号普通客户正在等待服务!第1号VIP窗口正在获取VIP服务号码第1号VIP窗口开始为第5号VIP客户服务第2号普通窗口正在获取普通服务号码第2号普通窗口没有取到普通服务号码休息一下第4号普通窗口正在获取普通服务号码第4号普通窗口没有取到普通服务号码休息一下第6号普通客户正在等待服务!第1号普通窗口为第1个普通客户完成服务耗费的时间:4秒 ---//一号普通窗口服务结束第1号普通窗口正在获取普通服务号码第1号普通窗口开始为第6号普通客户服务第2号普通窗口正在获取普通服务号码第2号普通窗口没有取到普通服务号码休息一下第7号普通客户正在等待服务!第4号普通窗口正在获取普通服务号码第4号普通窗口开始为第7号普通客户服务第4号快速客户正在等待服务!第2号VIP客户正在等待服务!第3号普通窗口为第3个普通客户完成服务耗费的时间:4秒第3号普通窗口正在获取普通服务号码第3号普通窗口没有取到普通服务号码休息一下第2号普通窗口正在获取普通服务号码第2号普通窗口没有取到普通服务号码休息一下第8号普通客户正在等待服务!第1号快速窗口为第4个快速客户完成服务耗费的时间:4秒第1号快速窗口正在获取快速服务号码第1号快速窗口开始为第3号快速客户服务第3号普通窗口正在获取普通服务号码第3号普通窗口开始为第8号普通客户服务第9号普通客户正在等待服务!第2号普通窗口正在获取普通服务号码第2号普通窗口开始为第9号普通客户服务第5号快速客户正在等待服务!第1号快速窗口为第3个快速客户完成服务耗费的时间:1秒第1号快速窗口正在获取快速服务号码第1号快速窗口开始为第4号快速客户服务第10号普通客户正在等待服务!第2号普通窗口为第9个普通客户完成服务耗费的时间:1秒第2号普通窗口正在获取普通服务号码第2号普通窗口开始为第10号普通客户服务第1号快速窗口为第4个快速客户完成服务耗费的时间:1秒第1号快速窗口正在获取快速服务号码第1号快速窗口开始为第5号快速客户服务第11号普通客户正在等待服务!第6号快速客户正在等待服务!第1号快速窗口为第5个快速客户完成服务耗费的时间:1秒第1号快速窗口正在获取快速服务号码第1号快速窗口开始为第6号快速客户服务第1号VIP窗口为第5个VIP客户完成服务耗费的时间:6秒第1号VIP窗口正在获取VIP服务号码第1号VIP窗口开始为第11号VIP客户服务第12号普通客户正在等待服务!第1号普通窗口为第6个普通客户完成服务耗费的时间:6秒第1号普通窗口正在获取普通服务号码第1号普通窗口开始为第12号普通客户服务
end......