------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

1.模拟实现银行业务调度系统逻辑,具体需求如下:

银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。

有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。

异步随机生成各种类型的客户,生成各类型用户的概率比例为:

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

客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需的时间,快速客户办理业务所需时间为最小值(提示:办理业务的过程可通过线程Sleep的方式模拟)。

各类型客户在其对应窗口按顺序依次办理业务。

当VIP(6号)窗口和快速业务(5号)窗口没有客户等待办理业务的时候,这两个窗口可以处理普通客户的业务,而一旦有对应的客户等待办理业务的时候,则优先处理对应客户的业务。

随机生成客户时间间隔以及业务办理时间最大值和最小值自定,可以设置。

不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。

2.类图:

3.NumberManager类
定义一个用于存储上一个客户号码的成员变量和用于存储所有等待服务的客户号码的队列集合。
定义一个产生新号码的方法和获取马上要为之服务的号码的方法,这两个方法被不同的线程操作了相同的数据,所以,要进行同步。

  1. public class NumberManager {
  2. private int lastNumber = 0;
  3. private List queueNumbers = new ArrayList();
  4. public synchronized Integer generateNewNumber(){
  5. queueNumbers.add(++lastNumber);
  6. return lastNumber;
  7. }
  8. public synchronized Integer fetchNumber(){
  9. if(queueNumbers.size()>0){
  10. return (Integer)queueNumbers.remove(0);
  11. }else{
  12. return null;
  13. }
  14. }
  15. }

4.NumberMachine类
定义三个成员变量分别指向三个NumberManager对象,分别表示普通、快速和VIP客户的号码管理器,定义三个对应的方法来返回这三个NumberManager对象。
将NumberMachine类设计成单例。

  1. public class NumberMachine {
  2. private NumberMachine(){}
  3. private static NumberMachine instance = new NumberMachine();
  4. public static NumberMachine getInstance(){
  5. return instance;
  6. }
  7. private NumberManager commonManager = new NumberManager();
  8. private NumberManager expressManager = new NumberManager();
  9. private NumberManager vipManager = new NumberManager();
  10. public NumberManager getCommonManager() {
  11. return commonManager;
  12. }
  13. public NumberManager getExpressManager() {
  14. return expressManager;
  15. }
  16. public NumberManager getVipManager() {
  17. return vipManager;
  18. }
  19. }

5.CustomerType枚举类
系统中有三种类型的客户,所以用定义一个枚举类,其中定义三个成员分别表示三种类型的客户。
重写toString方法,返回类型的中文名称。这是在后面编码时重构出来的,刚开始不用考虑。

  1. public enum CustomerType {
  2. COMMON,EXPRESS,VIP;
  3. public String toString(){
  4. String name = null;
  5. switch(this){
  6. case COMMON:
  7. name = "普通";
  8. break;
  9. case EXPRESS:
  10. name = "快速";
  11. break;
  12. case VIP:
  13. name = name();
  14. break;
  15. }
  16. return name;
  17. }
  18. }

6.ServiceWindow类
定义一个start方法,内部启动一个线程,根据服务窗口的类别分别循环调用三个不同的方法。 
定义三个方法分别对三种客户进行服务,为了观察运行效果,应详细打印出其中的细节信息。

  1. /**
  2. * 没有把VIP窗口和快速窗口做成子类,是因为实际业务中的普通窗口可以随时被设置为VIP窗口和快速窗口。
  3. * */
  4. public class ServiceWindow {
  5. private static Logger logger = Logger.getLogger("cn.itcast.bankqueue");
  6. private CustomerType type = CustomerType.COMMON;
  7. private int number = 1;
  8. public CustomerType getType() {
  9. return type;
  10. }
  11. public void setType(CustomerType type) {
  12. this.type = type;
  13. }
  14. public void setNumber(int number){
  15. this.number = number;
  16. }
  17. public void start(){
  18. Executors.newSingleThreadExecutor().execute(
  19. new Runnable(){
  20. public void run(){
  21. //下面这种写法的运行效率低,最好是把while放在case下面
  22. while(true){
  23. switch(type){
  24. case COMMON:
  25. commonService();
  26. break;
  27. case EXPRESS:
  28. expressService();
  29. break;
  30. case VIP:
  31. vipService();
  32. break;
  33. }
  34. }
  35. }
  36. }
  37. );
  38. }
  39. private void commonService(){
  40. String windowName = "第" + number + "号" + type + "窗口";
  41. System.out.println(windowName + "开始获取普通任务!");
  42. Integer serviceNumber = NumberMachine.getInstance().getCommonManager().fetchNumber();
  43. if(serviceNumber != null ){
  44. System.out.println(windowName + "开始为第" + serviceNumber + "号普通客户服务");
  45. int maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
  46. int serviceTime = new Random().nextInt(maxRandom)+1 + Constants.MIN_SERVICE_TIME;
  47. try {
  48. Thread.sleep(serviceTime);
  49. } catch (InterruptedException e) {
  50. e.printStackTrace();
  51. }
  52. System.out.println(windowName + "完成为第" + serviceNumber + "号普通客户服务,总共耗时" + serviceTime/1000 + "秒");
  53. }else{
  54. System.out.println(windowName + "没有取到普通任务,正在空闲一秒");
  55. try {
  56. Thread.sleep(1000);
  57. } catch (InterruptedException e) {
  58. e.printStackTrace();
  59. }
  60. }
  61. }
  62. private void expressService(){
  63. Integer serviceNumber = NumberMachine.getInstance().getExpressManager().fetchNumber();
  64. String windowName = "第" + number + "号" + type + "窗口";
  65. System.out.println(windowName + "开始获取快速任务!");
  66. if(serviceNumber !=null){
  67. System.out.println(windowName + "开始为第" + serviceNumber + "号快速客户服务");
  68. int serviceTime = Constants.MIN_SERVICE_TIME;
  69. try {
  70. Thread.sleep(serviceTime);
  71. } catch (InterruptedException e) {
  72. e.printStackTrace();
  73. }
  74. System.out.println(windowName + "完成为第" + serviceNumber + "号快速客户服务,总共耗时" + serviceTime/1000 + "秒");
  75. }else{
  76. System.out.println(windowName + "没有取到快速任务!");
  77. commonService();
  78. }
  79. }
  80. private void vipService(){
  81. Integer serviceNumber = NumberMachine.getInstance().getVipManager().fetchNumber();
  82. String windowName = "第" + number + "号" + type + "窗口";
  83. System.out.println(windowName + "开始获取VIP任务!");
  84. if(serviceNumber !=null){
  85. System.out.println(windowName + "开始为第" + serviceNumber + "号VIP客户服务");
  86. int maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
  87. int serviceTime = new Random().nextInt(maxRandom)+1 + Constants.MIN_SERVICE_TIME;
  88. try {
  89. Thread.sleep(serviceTime);
  90. } catch (InterruptedException e) {
  91. e.printStackTrace();
  92. }
  93. System.out.println(windowName + "完成为第" + serviceNumber + "号VIP客户服务,总共耗时" + serviceTime/1000 + "秒");
  94. }else{
  95. System.out.println(windowName + "没有取到VIP任务!");
  96. commonService();
  97. }
  98. }
  99. }

7.MainClass类
用for循环创建出4个普通窗口,再创建出1个快速窗口和一个VIP窗口。
接着再创建三个定时器,分别定时去创建新的普通客户号码、新的快速客户号码、新的VIP客户号码。

  1. public class MainClass {
  2. private static Logger logger = Logger.getLogger("cn.itcast.bankqueue");
  3. public static void main(String[] args) {
  4. //产生4个普通窗口
  5. for(int i=1;i<5;i++){
  6. ServiceWindow window =  new ServiceWindow();
  7. window.setNumber(i);
  8. window.start();
  9. }
  10. //产生1个快速窗口
  11. ServiceWindow expressWindow =  new ServiceWindow();
  12. expressWindow.setType(CustomerType.EXPRESS);
  13. expressWindow.start();
  14. //产生1个VIP窗口
  15. ServiceWindow vipWindow =  new ServiceWindow();
  16. vipWindow.setType(CustomerType.VIP);
  17. vipWindow.start();
  18. //普通客户拿号
  19. Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
  20. new Runnable(){
  21. public void run(){
  22. Integer serviceNumber = NumberMachine.getInstance().getCommonManager().generateNewNumber();
  23. /**
  24. * 采用logger方式,无法看到直观的运行效果,因为logger.log方法内部并不是直接把内容打印出出来,
  25. * 而是交给内部的一个线程去处理,所以,打印出来的结果在时间顺序上看起来很混乱。
  26. */
  27. //logger.info("第" + serviceNumber + "号普通客户正在等待服务!");
  28. System.out.println("第" + serviceNumber + "号普通客户正在等待服务!");
  29. }
  30. },
  31. 0,
  32. Constants.COMMON_CUSTOMER_INTERVAL_TIME,
  33. TimeUnit.SECONDS);
  34. //快速客户拿号
  35. Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
  36. new Runnable(){
  37. public void run(){
  38. Integer serviceNumber = NumberMachine.getInstance().getExpressManager().generateNewNumber();
  39. System.out.println("第" + serviceNumber + "号快速客户正在等待服务!");
  40. }
  41. },
  42. 0,
  43. Constants.COMMON_CUSTOMER_INTERVAL_TIME * 2,
  44. TimeUnit.SECONDS);
  45. //VIP客户拿号
  46. Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
  47. new Runnable(){
  48. public void run(){
  49. Integer serviceNumber = NumberMachine.getInstance().getVipManager().generateNewNumber();
  50. System.out.println("第" + serviceNumber + "号VIP客户正在等待服务!");
  51. }
  52. },
  53. 0,
  54. Constants.COMMON_CUSTOMER_INTERVAL_TIME * 6,
  55. TimeUnit.SECONDS);
  56. }
  57. }

8.Constants类
定义三个常量:MAX_SERVICE_TIME、MIN_SERVICE_TIME、COMMON_CUSTOMER_INTERVAL_TIME

    1. public class Constants {
    2. public static int MAX_SERVICE_TIME = 10000; //10秒!
    3. public static int MIN_SERVICE_TIME = 1000; //1秒!
    4. /*每个普通窗口服务一个客户的平均时间为5秒,一共有4个这样的窗口,也就是说银行的所有普通窗口合起来
    5. * 平均1.25秒内可以服务完一个普通客户,再加上快速窗口和VIP窗口也可以服务普通客户,所以,
    6. * 1秒钟产生一个普通客户比较合理,*/
    7. public static int COMMON_CUSTOMER_INTERVAL_TIME = 1;
    8. }

黑马程序员_JAVA之银行业务调度系统的更多相关文章

  1. 黑马程序员_java基础笔记(15)...银行业务调度系统_编码思路及代码

    —————————— ASP.Net+Android+IOS开发..Net培训.期待与您交流!—————————— 1,面试题目:银行业务调度系统 模拟实现银行业务调度系统逻辑,具体需求如下: 银行内 ...

  2. 黑马程序员_Java基础:多线程总结

    ------- android培训.java培训.期待与您交流! ---------- 一.多线程的概念 进程和线程经常会被人混淆,那是因为对它们的概念不明确.就拿我们平时使用的操作系统来说,它是多任 ...

  3. 黑马程序员_Java基础:网络编程总结

    ------- android培训.java培训.期待与您交流! ---------- Java语言是在网络环境下诞生的,它是第一个完全融入网络的语言,虽然不能说它是对支持网络编程做得最好的语言,但是 ...

  4. 黑马程序员_Java基础视频-深入浅出精华版--PPT 文件列表

    \day01\code\第一章_Java概述.ppt;\day01\resource\资料\50道编程题(有精力的同学看看).doc;\day01\resource\资料\Sun_Java程序员认证考 ...

  5. 黑马程序员_Java基础组成

    Java语言基础组成 2.1关键字 main不是关键字,但被JVM所识别的名称. 关键字的定义和特点 定义:被Java语言赋予了特殊含义的单词. 特点:关键字中所有字母都为小写. 用于定义数据类型的关 ...

  6. 黑马程序员_Java泛型

    泛型 概述: ClassCaseException:类型转换异常. 代码中不加泛型,编译没问题,运行可能会发生异常.但是用户解决不了,这样程序就存在安全隐患.所以我们希望在编译时期就能看出问题,程序员 ...

  7. 黑马程序员_JAVA之交通灯管理系统

    ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 1.一.需求:模拟实现十字路口的交通灯管理系统逻辑,具体需求如下:  1.异步随机生成按照各个路 ...

  8. 黑马程序员_JAVA基础知识总结3

    ------- android培训.java培训.期待与您交流! ---------- Java源文件的扩展名是.java,编译之后生成.class的文件.所有的类都有一个共同的继承祖先Object类 ...

  9. 黑马程序员_JAVA基础知识总结2

    ------- android培训.java培训.期待与您交流! ---------- IDE ---> Itegrity Development Environment Java EE --- ...

随机推荐

  1. 关于PDF文件无法打印的问题的解决办法

    在这里用到一个软件 PDFSpliter可以直接在网上下载.下载安装完之后 1:打开软件 2,点击   PDF合并  按钮 3,找到无法打印的文件 4,单击开始,文件另存为 5,另存为后的文件就可以打 ...

  2. jquery 调用ajax返回json

    ie调用可以,火狐和chrome皆失败,找了半天原因. 被屏蔽了. 火狐和chrome 对同一个域名不同端口的调用也严格限制,不给调用.只能用jsonp. 查看网络的返回状态,错误信息,F12 很重要 ...

  3. C语言获得数组长度的函数

    <转自百度知道> 1.c语言中,定义数组后可以用sizeof命令获得数组的长度(可容纳元素个数). 例如: int data[4]; int length; length=sizeof(d ...

  4. tornado 协程的实现原理个人理解;

    tornado实现协程的原理主要是利用了(1)python里面的generator (2)future类和ioloop相互配合,两者之间的相互配合是通过gen.coroutine装饰器来实现的: 具体 ...

  5. 关于工伤事故索赔计算很好用的一款APP

    关于工伤事故索赔计算很好用的一款APP.详细介绍工伤伤残等级评估 工伤计算器根据国家颁布<劳动能力鉴定 职工工伤与职业病致残等级>,通过关键字检索,快速评估工伤伤残等级. 软件说明:  1 ...

  6. 动手实现自己的 STL 容器《2》---- list

    1. 序: 本文参考了侯捷的 <STL 源码分析>一书,出于兴趣,自行实现了简单的 list 容器. 学习了 STL 的 list 容器的源代码,确实能够提高写链表代码的能力.其中的 so ...

  7. Maven项目中的run as选项介绍

    maven install:把本项目发布到本地资源库maven package:编译.测试,然后打包项目maven test:执行测试maven clean:把该资源从本地资源库清除.在基于Maven ...

  8. surge for mac出测试版本了

    这两天一直在MAC上试图连接我的shadowsocks服务,使用shadowsocksX一直没能连接到服务器.服务器本身是没有问题的,因为我的thinkpad和iphone都可以正常使用.结果就试着使 ...

  9. 转 通过js获取cookie的实例及简单分析

    今天review新人写的javascript代码的时候发现了很多的问题.这里以function getCookie(name){}为例. 其中比较典型的一个问题就是如何通过javascript获取co ...

  10. 论文笔记之:Deep Attention Recurrent Q-Network

    Deep Attention Recurrent Q-Network 5vision groups  摘要:本文将 DQN 引入了 Attention 机制,使得学习更具有方向性和指导性.(前段时间做 ...