银行业务调度
来源:互联网 发布:淘宝与阿里巴巴的关系 编辑:程序博客网 时间:2024/05/29 04:27
张孝祥老师7k面试题之银行业务调度:
这道题还是有些难度的,不过一步一步分析,也不那么难理解,本片博客重点说说思路:
一.需求分析:
(1)银行内有6个业务窗口, 4个普通窗口,1快速窗口,1个VIP窗口。
(2)有三种对应类型的客户:VIP客户,普通客户,快速客户。(3)VIP客户以及普通客户办理业务所需的时间有最大值和最小值,快速客户办理业务所需时间为最小值,三种客户比例为VIP客户:普通客户 :快速客户 = 1 :6 :3。
(4)当VIP窗口和快速窗口没有客户等待可以为普通客户服务
二.用面相对象的思想可以提炼出三个对象,
1.银行窗口,
2.号码生成器(可以生成三种对应类型的客户的号码),
3.号码管理器(生成号码和获取窗口马上要服务的号码)
三.整个流程可这样设计:
1.号码管理器产生新号码,并对外提供获取窗口马上要办理的号码的方法。
2.号码生成器,由于只想它在内存中只有一个对象,采用单例设计,并在里面定义3个指向号码管理器的属性对象,分别表示普通客户,快速客户,vip客户。并对外提供访问对象的的方法。
3.开启一个线程循环调用3种窗口那类型,线程种根据不同客户,调用不同的窗口,用executors线程池。可以有switch() case :去判断怎么调用。类型这个变量只有3种考虑用枚举去定义。用if()else()去判断该类型窗口有没有等待的服务的号码,如果是快速窗口和vip窗口没有等待的,就为普通窗口服务。
4.主函数:创建6个窗口,并定于3个定时器,分别去创建新的普通号码,新的快速号码,新的vip号码。(定时器用execoutor接口创建)
四 .具体步骤:
1. 创建号码管理器类:
(1) 定义一个变量记录上一个客户的号码,方便得道下一个客户号码。
(2) 定义一个集合,存储在排队的号码。
(3) 定义一个方法可以产生新的号码。
(4) 定义一个方法能够给窗口提供马上要服务的号码。
(面相对象的思想:谁拥有数据谁对外提供方法。)
代码体现:
public class NumberManager {/*步骤:1定义一个变量记录上一个生成了多少号,方便给下一个多少号。2定义一个集合来装还没有服务的号 * 3创建取号的方法,4创建个给窗口多少号的方法。* * 说明3,4是不同线程操作相同 的数据需要同步*/ private int lastNumber=0; private List< Integer> queueNumbers = new ArrayList<Integer>(); //定义方法生成号码 public synchronized Integer shengChengNumber(){ queueNumbers.add(++lastNumber); return lastNumber; } //为窗口获取号码 public synchronized Integer quChuNumber(){ if(queueNumbers.size()>0){ return queueNumbers.remove(0); }else{ return null; } }}
(注意:不同线程操作共享资源,需要加锁。)
2. 号码生成器由于只想它在内存中只有一个对象,采用单例设计,并在里面定义3个指向号码管理器的属性对象,分别表示普通客户,快速客户,vip客户。并对外提供访问对象的的方法。
(1) 单例设计号码管理器类
(2) 定义3个属性对象
提供方法返回号码管理器对像。
public class Numbermachne {/*号码管理器:1.定义变量指向numbermanager对象,分别表示普通,快速,vip。 * 2定义3个方法返回3个对象 * 3 把号码管理器设为单例*///用单例设计,让号码管理器的对象只有一个。private Numbermachne (){};private static Numbermachne instance = new Numbermachne();public static Numbermachne getinstance(){return instance;}//创建三个属性,分别表示普通客服,快速客服,vip客服。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, (1)定义3种客服窗口的枚举:
(2)开启一个线程,循环调用不同的服务窗口(需要使用executors线程池)
(3)如果快速窗口和vip窗口没有服务的号码,调用普通窗口的服务。
public enum Customer {COMMON,EXPRESS,VIP;public String toString(){String name = null;switch (this) {case COMMON:name="普通客服";break;case EXPRESS:name="快速客服";break;case VIP:name="VIP客服";break;}return name;}public class ServiceWindow { private static Logger logger = Logger.getLogger("cn.itcast.bankqueue"); private Customer type = Customer.COMMON; private int number = 1; public Customer getType() { return type; } public void setType(Customer type) { this.type = type; } public void setNumber(int number){ this.number = number; } public void start(){ Executors.newSingleThreadExecutor().execute( new Runnable(){ public void run(){ //下面这种写法的运行效率低,最好是把while放在case下面 while(true){ switch(type){ case COMMON: commonService(); break; case EXPRESS: expressService(); break; case VIP: vipService(); break; } } } } ); } private void commonService(){ String windowName = "第" + number + "号" + type + "窗口"; System.out.println(windowName + "开始获取普通任务!"); Integer serviceNumber = NumberMachine.getInstance().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; 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(); } } } private void expressService(){ Integer serviceNumber = NumberMachine.getInstance().getExpressManager().fetchNumber(); String windowName = "第" + number + "号" + type + "窗口"; 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(); } System.out.println(windowName + "完成为第" + serviceNumber + "号快速客户服务,总共耗时" + serviceTime/1000 + "秒"); }else{ System.out.println(windowName + "没有取到快速任务!"); commonService(); } } private void vipService(){ Integer serviceNumber = NumberMachine.getInstance().getVipManager().fetchNumber(); String windowName = "第" + number + "号" + type + "窗口"; System.out.println(windowName + "开始获取VIP任务!"); if(serviceNumber !=null){ System.out.println(windowName + "开始为第" + serviceNumber + "号VIP客户服务"); int maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME; int serviceTime = new Random().nextInt(maxRandom)+1 + Constants.MIN_SERVICE_TIME; try { Thread.sleep(serviceTime); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(windowName + "完成为第" + serviceNumber + "号VIP客户服务,总共耗时" + serviceTime/1000 + "秒"); }else{ System.out.println(windowName + "没有取到VIP任务!"); commonService(); } } } }
4主函数:(1)创建窗口对象,4个普通窗口,1个快速窗口,1个vip窗口
(2)创建3个定时期,定时创建普通号码,快速号码,vip号码。
public class MainClass { private static Logger logger = Logger.getLogger("cn.itcast.bankqueue"); public static void main(String[] args) { //产生4个普通窗口 for(int i=1;i<5;i++){ ServiceWindow window = new ServiceWindow(); window.setNumber(i); window.start(); } //产生1个快速窗口 ServiceWindow expressWindow = new ServiceWindow(); expressWindow.setType(CustomerType.EXPRESS); expressWindow.start(); //产生1个VIP窗口 ServiceWindow vipWindow = new ServiceWindow(); vipWindow.setType(CustomerType.VIP); vipWindow.start(); //普通客户拿号 Executors.newScheduledThreadPool(1).scheduleAtFixedRate( new Runnable(){ public void run(){ Integer serviceNumber = NumberMachine.getInstance().getCommonManager().generateNewNumber(); /** * 采用logger方式,无法看到直观的运行效果,因为logger.log方法内部并不是直接把内容打印出出来, * 而是交给内部的一个线程去处理,所以,打印出来的结果在时间顺序上看起来很混乱。 */ //logger.info("第" + serviceNumber + "号普通客户正在等待服务!"); 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().generateNewNumber(); 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().generateNewNumber(); System.out.println("第" + serviceNumber + "号VIP客户正在等待服务!"); } }, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME * 6, TimeUnit.SECONDS); } }
0 0
- 银行业务调度
- 银行业务调度
- 银行业务调度
- 银行业务调度
- 银行业务调度系统
- 银行业务调度系统笔记
- 银行业务调度系统
- 银行业务调度系统心得
- 银行业务调度系统
- 银行业务调度系统
- 银行业务调度系统学习
- 银行业务调度系统
- 银行业务调度系统
- 银行业务调度系统
- 银行业务调度系统
- 银行业务调度系统
- 银行业务调度系统
- 银行业务额调度系统
- 分公司电脑通过大手笔投入
- Security Lab
- Josephus Problem
- Can't connect to local MySQL server through socket '/tmp/mysql.sock'解决
- 分公司电脑通过大手笔投入
- 银行业务调度
- JavaScript初学小结
- 分公司电脑通过大手笔投入
- 使用boost中的线程池
- 分公司电脑通过大手笔投入
- Codeforces Round #107 (Div. 2) B (简单模拟)
- android:label="@string/app_name"> 的含义
- 分公司电脑通过大手笔投入
- 分公司电脑通过大手笔投入