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

银行业务调度系统项目需求:

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

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

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

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

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

>>客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需的时间,快速客户办理业务所需

     时间为最小值。

    (提示:办理业务的过程可通过线程Sleep的方式模拟)

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

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

     待办理业务的时候,则优先处理对应客户的业务。 

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

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

面向对象的分析与设计:

客户(共有3种类型)

VIP客户、普通客户、快速客户

异步随机生成各种类型的客户,各类型客户在其对应的窗口按顺序办理业务。

“号码产生器”:产生号码,号码也可以理解为客户。

“号码管理器”:因为有3种客户,所以要有3种相对独立的号码生成器,但是取号机就一个,可以把这3个生成器放到一个号码管理器中,因为

这个机器就一个,所以要被设计成单例。

窗口依次叫号:(也就是说可以理解为:各个类型客户在其对应窗口依次办理业务)

窗口如何叫号呢?必然是问号码管理器

类名称

方法

功能简述

NumberMachine

(银行取号码的机器)

(注:号码机器管理3个号码生成器)

 

 

getCommonManager()

普通客户管理器

getVipManager()

VIP客户管理器

getExpressManager()

快速客户管理器

getInstance()

静态方法,单例

NumberManager

(号码生成器)

generateNewNumber()

产生号码(为客户而生)

 

 

fetchNumber()

取号,即将要服务的号码

(为窗口服务)

ServiceWindow ()

start()

开始服务

commonService()

普通服务窗口

expressService()

快速服务窗口

vipService()

vip服务窗口

 

(***注:参考一下,面向对象的一个重要原则:谁拥有数据,那么对这些数据进行操作的方法就交给谁。)

详细设计:(工程名BankQueue)

一:类

1,号码生成器

NumberManager.class

 

产号方法generateNewManager()

取号方法fetchServiceNumber()

 

2,号码管理器

NumberMachine.class

 

普通客户commonManager

快速客户expressManager

vip客户vipManager

 

3,服务窗口

ServiceWindow.class

 

类型type

顺序number

 

开始方法start()

普通窗口服务commonService()

快速窗口服务expressService()

vip 窗口服务 vipService()

 

4, 定义一个枚举类型

CustomerType.class

 

COMMON普通

EXPRESS快速

VIP

 

转换成中文toString()

 

5,定义常量

Constants.class

 

最大休息时间MAX_SERVICE_TIME

最小休息时间MIN_SERVICE_TIME

产生客户时间COMMON_CUSTOMER_INTERVAL_TIME

 

6,测试类

MainClass.class

 

4个普通窗口

1个快速窗口

1个VIP窗口

 

1个普通拿号线程

1个快速客户拿号

1个VIP客户拿号

 

二.部分所需类以及方法整理:

(1)

ExecutorService pool = Executors.newScheduledThreadPool(1). scheduleAtFixedRate(1,2,3,4)/*看下面*/;

创建一个线程池,-------------线程池(线程数)

 

ScheduledFuture<?>  scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)

//创建并执行开始时间,然后过了多少秒之后继续干,再过多少秒再干, 再过多少秒再干, 再过多少秒再干......

//(线程,过多少秒之后去做,然后过多少秒再去干,时间单位)

 

(2)

new Random().nextInt(10)

//返回0~9的随机数

 

 

代码实现:

------------------NumberManager.java--------------------

 1 package cn.itcast.interview.bank;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 //1,号码生成器
 7 public class NumberManager {
 8 
 9     //上一次产生的号码
10     private int lastNumber=1;
11     
12     //定义一个队列 动态数组(集合)
13     //面向接口编程,所以前面用List,用List的扩展性更大.
14     private List<Integer> queueNumber = new ArrayList<Integer>();
15     
16     //①产生号码,因为有可能引发同步,就是说多个线程操作一个数据,所以要用synchronized修饰,使线程同步
17     public synchronized Integer generateNewManager()
18     {    
19         //将号码存起来
20         queueNumber.add(lastNumber); 
21         //返回到下一个号码
22         return lastNumber++;
23     }
24     
25     //②取方法,同样有synchronized,当多个线程同时操作①②时,会产生互斥
26     //说一下返回类型Integer(可以自动装箱,拆箱),为了避免没有取到号码返回null,int话会造成空指针异常
27     public synchronized Integer fetchServiceNumber()
28     {
29         //将号码取走,
30         if(queueNumber.size()>0)
31         {
32             return (Integer)queueNumber.remove(0);
33         }
34         else
35         {
36             return null;
37         }
38         
39     }
40 }
NumberManager.java

------------------NumberMachine.java---------------------

 1 package cn.itcast.interview.bank;
 2 //2,号码管理器
 3 public class NumberMachine {
 4     //要返回3个管理器
 5     private NumberManager commonManager = new NumberManager();//普通客户
 6     private NumberManager expressManager = new NumberManager();//快速客户
 7     private NumberManager vipManager = new NumberManager();//vip客户
 8     
 9     public NumberManager getCommonManager() {
10         return commonManager;
11     }
12     public NumberManager getExpressManager() {
13         return expressManager;
14     }
15     public NumberManager getVipManager() {
16         return vipManager;
17     }
18     //因为就一个对象,所以要做成单例.第一步为上面的所有代码,就是说先做成一个普通对象
19     //第二步
20     //首先,构造方法私有化
21     private NumberMachine(){}
22     
23     //第三步紧接着,因为不能new对象了.所以必须创建一个静态方法.静态方法返回自己类的一个对象
24     public static NumberMachine getInstance()//getInstance意思:获得实例,大家都这么叫-_-!!
25     {
26         return instance;
27     }
28     //上面返回的自己的对象所以下面必须要有变量名,而且是静态的
29     private static NumberMachine instance= new NumberMachine();
30     
31 }
NumberMachine.java

-------------------ServiceWindow.java---------------------

  1 package cn.itcast.interview.bank;
  2 
  3 import java.util.Random;
  4 import java.util.concurrent.Executors;
  5 import java.util.logging.Logger;
  6 
  7 /**
  8  * 没有把VIP窗口和快速窗口做成子类,是因为实际业务中的普通窗口可以随时被设置为VIP窗口和快速窗口。
  9  *
 10 3,服务窗口
 11  */
 12 public class ServiceWindow {
 13     @SuppressWarnings("unused")
 14     private static Logger logger = Logger.getLogger("cn.itcast.bankqueue");
 15     //定义一个变量,来判断是哪一种类型的窗口,请看完CustomerType之后,继续回来,默认值为COMMON
 16     private CustomerType type = CustomerType.COMMON;
 17     //定一个顺序
 18     private int number = 1;
 19 
 20     public CustomerType getType() {
 21         return type;
 22     }
 23 
 24     public void setType(CustomerType type) {
 25         this.type = type;
 26     }
 27     
 28     public void setNumber(int number){
 29         this.number = number;
 30     }
 31     //给只能给外部一个开始的方法
 32     public void start(){
 33         //new线程池,到这个线程池的内部招空闲的线程运行
 34         Executors.newSingleThreadExecutor().execute(
 35                 new Runnable(){
 36                     public void run(){
 37                         //下面这种写法的运行效率低,最好是把while放在case下面
 38                         ////这里要实现的就是去取号
 39                         while(true){
 40                             switch(type){
 41                                 case COMMON:
 42                                     commonService();
 43                                     break;
 44                                 case EXPRESS:
 45                                     expressService();
 46                                     break;
 47                                 case VIP:
 48                                     vipService();
 49                                     break;
 50                             }
 51                         }
 52                     }
 53                 }
 54         );
 55     }
 56     
 57     private void commonService(){
 58         String windowName = "第" + number + "号" + type + "窗口";        
 59         System.out.println(windowName + "开始获取普通任务!");
 60         Integer serviceNumber = NumberMachine.getInstance().getCommonManager().fetchServiceNumber();        
 61         if(serviceNumber != null ){
 62             //定义开始时间
 63             System.out.println(windowName + "开始为第" + serviceNumber + "号普通客户服务");        
 64             //最大服务时间
 65             int maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
 66             //服务的时间(产生一个随机时间,因为服务时间是0~8,所以+1.也就是1~9秒之间也就是1000~9000,再加上1000也就是
 67                                                                                                 //基数为1,再加上1~9)
 68             int serviceTime = new Random().nextInt(maxRandom)+1 + Constants.MIN_SERVICE_TIME;
 69             //睡眠时间
 70             try {
 71                 Thread.sleep(serviceTime);
 72             } catch (InterruptedException e) {
 73                 e.printStackTrace();
 74             }    
 75             System.out.println(windowName + "完成为第" + serviceNumber + "号普通客户服务,总共耗时" + serviceTime/1000 + "秒");        
 76         }else{
 77             System.out.println(windowName + "没有取到普通任务,正在空闲一秒");        
 78             try {
 79                 Thread.sleep(1000);//没有取到任务,就休息一秒钟,然后再继续
 80             } catch (InterruptedException e) {
 81                 e.printStackTrace();
 82             }                
 83         }
 84     }
 85     
 86     private void expressService(){
 87         Integer serviceNumber = NumberMachine.getInstance().getExpressManager().fetchServiceNumber();
 88         String windowName = "第" + number + "号" + type + "窗口";    
 89         System.out.println(windowName + "开始获取快速任务!");        
 90         if(serviceNumber !=null){
 91             System.out.println(windowName + "开始为第" + serviceNumber + "号快速客户服务");            
 92             int serviceTime = Constants.MIN_SERVICE_TIME;//快读客户服务时间
 93             try {
 94                 Thread.sleep(serviceTime);//休息时间,只能是最小值
 95             } catch (InterruptedException e) {
 96                 e.printStackTrace();
 97             }        
 98             System.out.println(windowName + "完成为第" + serviceNumber + "号快速客户服务,总共耗时" + serviceTime/1000 + "秒");        
 99         }else{
100             System.out.println(windowName + "没有取到快速任务!");                
101             commonService();
102         }
103     }
104     
105     private void vipService(){
106 
107         Integer serviceNumber = NumberMachine.getInstance().getVipManager().fetchServiceNumber();
108         String windowName = "第" + number + "号" + type + "窗口";    
109         System.out.println(windowName + "开始获取VIP任务!");            
110         if(serviceNumber !=null){
111             System.out.println(windowName + "开始为第" + serviceNumber + "号VIP客户服务");            
112             int maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
113             int serviceTime = new Random().nextInt(maxRandom)+1 + Constants.MIN_SERVICE_TIME;
114             try {
115                 Thread.sleep(serviceTime);
116             } catch (InterruptedException e) {
117                 e.printStackTrace();
118             }        
119             System.out.println(windowName + "完成为第" + serviceNumber + "号VIP客户服务,总共耗时" + serviceTime/1000 + "秒");        
120         }else{
121             System.out.println(windowName + "没有取到VIP任务!");                
122             commonService();
123         }    
124     }
125 }
ServiceWindow.java

--------------------CustomerType.java---------------------

 1 package cn.itcast.interview.bank;
 2 //4枚举一个类型
 3 public enum CustomerType {
 4     //COMMON,普通
 5     //EXPRESS快速
 6     //VIP
 7     COMMON,EXPRESS,VIP;
 8     
 9     //将参数转变成中文.(又恍然大悟的感觉.....)
10     public String toString()
11     {
12         String name = null;
13         switch(this)
14         {
15         case COMMON:
16         name = "普通";
17         
18         case EXPRESS:
19         name =  "快速";
20         break;
21         case VIP:
22         name = name();
23         break;
24         }
25         return name;
26     }
27 }
CustomerType.java

----------------------Constants.java------------------------

 1 package cn.itcast.interview.bank;
 2 //5,定义常量
 3 public class Constants {
 4     //最大休息时间
 5     public static int MAX_SERVICE_TIME=10000;
 6     
 7     //最小休息时间
 8     public static int MIN_SERVICE_TIME=1000;
 9     
10     /*每个普通窗口服务一个客户的平均时间为5秒,一共有4个这样的窗口,也就是说银行的所有普通窗口合起来
11      * 平均1.25秒内可以服务完一个普通客户,再加上快速窗口和VIP窗口也可以服务普通客户,所以,
12      * 1秒钟产生一个普通客户比较合理,*/    
13     public static int COMMON_CUSTOMER_INTERVAL_TIME = 1;     
14     
15 }
Constants.java

---------------------MainClass.class-------------------------

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

 

 

posted on 2013-12-24 15:10  毛线球球  阅读(173)  评论(0编辑  收藏  举报

导航