黑马程序员_JAVA之银行业务调度系统

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

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

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

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

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

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

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

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

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

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

2.类图:

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

[java] view plaincopy

  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类设计成单例。

[java] view plaincopy

  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方法,返回类型的中文名称。这是在后面编码时重构出来的,刚开始不用考虑。

[java] view plaincopy

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

[java] view plaincopy

  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客户号码。

[java] view plaincopy

  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

[java] view plaincopy

    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. }
时间: 2024-10-12 20:49:09

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

黑马程序员-java-银行业务调度系统《十一》

                   --Java培训.Android培训.iOS培训..Net培训.期待与您交流! -- 1.了解银行业务调度系统的工作流程与原理 银行里有三种窗口,一种是普通窗口,一种是VIP窗口,一种是快速窗口,所有客户都要领号排队,当VIP窗口或快速窗口空闲时,可以为普通窗口服务. 2.银行业务调度系统的项目需求 · 银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口. · 有三种对应类型的客户:VIP客户,普通客户,快速客户(办理

黑马程序员__缴费业务调度系统

缴费业务调度系统: 模拟实现缴费业务调度系统逻辑,具体需求如下: 银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口. 有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费.电话费之类业务的客户). 异步随机生成各种类型的客户,生成各类型用户的概率比例为: VIP客户 :普通客户 :快速客户  =  1 :6 :3. 客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需的时间,快速客户办理业务所需时

黑马程序员_Java基础加强(下)

8.注解类 注解相当于一种标记,加了注解就等于打上了某种标记,没加就等于没打特殊标记,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记就去干什么事,标记可以加在包.类.字段.方法,方法的参数以及局部变量上. 注解的应用结构图: 为注解增加属性 定义基本类型的属性和应用属性 在注解类中增加String color(); @MyAnnotation(color = "red") 用反射方式获得注解对应的实例对象后,再通过该对象调用属性对应的方法 MyAnno

黑马程序员_Java基础加强(上)

1.静态导入 静态导入是jdk1.5版本以后出现的新特性,一般是指导入静态方法,如:import static java.lang.System.out 是指导入系统输出的静态方法. 例: import static java.lang.System.out //导入java.lang包下的System类的静态方法out public class StaticImport { public static void main(String[] args) { int x=1; x++; out.p

黑马程序员_Java高新技术

1  JDK5的新特性 1.1 静态导入       在API中那些不需要new对象的类,可以在类文件的开头,import static java.lang.Math.*;这里把Math中的所有的静态方法都导入了,在类中不需要调用Math类就能直接用Math的方法了 package cn.wjd.staticimport; import static java.lang.Math.*; public class StaticImport { public static void main(Str

黑马程序员_Java多线程

- - - - - android培训.java培训.期待与您交流! - - - - - - 进程:正在进行中的程序.其实进程就是一个应用程序运行时的内存分配空间.进程负责的是应用程序的空间的标示. 线程:其实就是进程中一个程序执行控制单元,一条执行路径.线程负责的是应用程序的执行顺序. 一个进程至少有一个线程在运行,当一个进程中出现多个线程时,就称这个应用程序是多线程应用程序. 每个线程在栈区中都有自己的执行空间,自己的方法区.自己的变量. jvm在启动的时,首先有一个主线程,负责程序的执行,

黑马程序员_Java环境搭建及语言基础

- - - - android培训.java培训.期待与您交流!- - - - - - JRE和JDK JRE:Java Runtime Environment,java运行环境. JDK:Java Development Kit,java开发工具包. 使用JDK开发java程序,交给JRE运行. JDK下载和安装 http://www.oracle.com/technetwork/java/javase/downloads/index.html JDK的目录结构 目录/文件名 功能说明   b

黑马程序员_Java基础_接口

------- android培训.java培训.期待与您交流! ---------- 0.接口知识体系 Java接口的知识体系如下图所示,掌握下图中的所有知识就可精通接口. 1.接口概论 1)接口概念 接口是从多个相似类中抽象出来的规范,接口中不包含普通方法,所有方法都是抽象方法,接口不提供实现.接口体现的是规范和实现分离的哲学.规范和实现分离正是接口的好处,让软件系统的各个组件之间面向接口耦合,是一种松耦合的设计.接口定义的是多个类共同的公共行为规范,定义的是一组公用方法. 2)接口与抽象类

黑马程序员_Java异常 Java常用库类

Java异常 1,异常的基本概念 异常是导致程序中断运行的一种指令流,它是在运行时期发生的不正常的情况,在Java中,一切的异常都秉着面向对象的设计思想,所有的异常都是以对象和类的形式存在的. 2,异常类的继承结构 在整个Java的异常结构中,实际上有两个最常用的类,Exception和Error,这两个类分别是Throwable的子类 Exception:一般表示的是程序中出现的问题,可以直接使用try....catch处理 Error:一般之的是JVM的错误,程序中无法处理. 3,Java的