------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. javascript的坑

    1 for in循环:使用它时,要主要遍历的是所有可枚举的属性(实例以及原型中的属性) function Person(name){ this.name = name; } Person.protot ...

  2. 实现手机扫描二维码页面登录,类似web微信-第二篇,关于二维码的自动生成

    转自:http://www.cnblogs.com/fengyun99/p/3541251.html 接上一章,我们已经基本把业务逻辑分析清楚了 下面我们第一步,实现二维码的web动态生成. 页面的二 ...

  3. AsyncTask的基本使用和各个参数的说明

    AsyncTask 的执行分为四个步骤,每一步都对应一个回调方法,需要注意的是这些方法不应该由应用程序调用,开发者需要做的就是实现这些方法.在任务的执行过程中,这些方法被自动调用. * onPreEx ...

  4. java基础介绍(转)

    很全面的介绍JAVA基础的文档 Java 编程简介,第 1 部分: Java 语言基础 http://www.ibm.com/developerworks/cn/java/j-introtojava1 ...

  5. pdf 显示

    昨天调用同事写好的显示pdf借口  他返回给我的byte 我这面进行接受流的时候  长度一直跟他的对应不上 最后用WebClient类进行解决 webclient类 第一种是将文件存储在文件系统上,用 ...

  6. checkbox选中与取消选择

    先上代码 <form> 你爱好的运动是?<br/> <input type="checkbox" name="items" val ...

  7. 一行代码从表中选取N行到另一个表

    private void Form1_Load(object sender, EventArgs e) {            DataTable dt = new DataTable();     ...

  8. H - R(N)

    H - R(N) Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Sta ...

  9. c++作用域运算符---7

    原创博客:转载请标明出处:http://www.cnblogs.com/zxouxuewei/ ::是C++里的“作用域运算符”. 比如声明了一个类A,类A里声明了一个成员函数void f(),但没有 ...

  10. 线段树(segment tree)

    线段树在一些acm题目中经常见到,这种数据结构主要应用在计算几何和地理信息系统中.下图就为一个线段树: (PS:可能你见过线段树的不同表示方式,但是都大同小异,根据自己的需要来建就行.) 1.线段树基 ...