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

----------- android培训java培训、java学习型技术博客、期待与您交流! ------------


1、业务分析:

模拟整个银行大厅的工作,需要在大脑中构建银行大厅的场景。主要是两个过程。1)、陆续随机进入三种类型(普通、快速服务、vip)的客户,他们去取票排队,取号机分类将他们内在的划分为了3个不同的队列(号码性质不同),每当一个用户去被服务了,那么就销毁这一个号码,每当进入一个客户,相应的增加一个号码。2)、窗口的工作人员不停的工作,他们会根据窗口的属性、根据服务对象的队列号去叫下一个人来办理业务。Vip窗口和快速窗口当本类的业务客户都处理完了,就去帮助普通窗口工作。

注意:三类客户的产生比例不同,1:3:6,用线程的周期时间来控制,没个周期内都产生一个相应类型的客户,那么把周期时间控制到1:3:6则就让用户数量呈现这个比例了。且不同的客户在办理业务时时间也是不同的,有一个范围限定,普通客户和vip客户在范围内随机,快速用户为最小办理时间,sleep模拟。

 

2、类规划:

NumberMachine:取号机,一个大厅只有一个取号机,所以单例实现。同时该取号机内存在三种号码管理器,分别对应三种客户的号码管理。同时使用线程提供三种号码管理器的业务工作,即产生用户。

NumberManage:虽然有三种用户,但是他们产生号码的号码管理器工作方式都是一样的,封装成一个类,在NumberMachine中创建3个对象即可;使用一个List属性存放用户编号。提供添加用户的方法。提供获取队列最首用户的方法给窗口业务员去调用。

ServiceWindow:提供一个ID属性和TYPE属性(类型显然是枚举),同时为该两种属性提供set方法,而不是在构造器中绑定IDTYPE,更符合实际情况,因为窗口实际生活中可以改变属性的。该类还根据3种窗口类型分别3种业务处理方法,使用线程实现,不停叫号工作。

CustomerType:枚举类,为ServiceWindowTYPE属性提供值。方便使用,重写toString方法,

Constants:常量类,存放系统中使用的常量。

BankSystem:系统工作类。

3、具体实现:

 NumberManager.java

[java] view plaincopy
  1. package blog13Bank;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. // 号码管理器,用户号码产生的类  
  7. public class NumberManager {  
  8.     private int lastNumber = 0;  
  9.     private List<Integer> queue = new ArrayList<>();  
  10.       
  11.     public synchronized Integer newCustomer(){ /*设置成线程锁的方法,因为该方法用NumberMachine的对象调用 
  12.         而叫号去办理用户的方法由ServiceWindow窗口类调用,不同类共同访问queue会线程安全问题,所以加锁*/  
  13.         queue.add(++lastNumber);  
  14.         return lastNumber;  
  15.     }  
  16.       
  17.      public synchronized Integer fetchNumber(){  
  18.          if(queue.size()>0){  
  19.              return queue.remove(0); //取走队首元素,  
  20.          }  
  21.          return null;//队列为空,没有用户,就返回null4,所以方法返回值需要设置成Integer  
  22.      }  
  23. }  


NumberMachine.java

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package blog13Bank;  
  2. // 取号机,是一个单例,先当普通类实现业务,再将类写成单例  
  3. public class NumberMachine {  
  4.     private NumberManager commonManager = new NumberManager();  
  5.     private NumberManager expressManager = new NumberManager();  
  6.     private NumberManager vipManager = new NumberManager();  
  7.     //创建三个号码管理器,并提供get获取方法  
  8.     public NumberManager getCommonManager() {  
  9.         return commonManager;  
  10.     }  
  11.     public NumberManager getExpressManager() {  
  12.         return expressManager;  
  13.     }  
  14.     public NumberManager getVipManager() {  
  15.         return vipManager;  
  16.     }  
  17.       
  18.     //写成单例  
  19.     private NumberMachine(){}  
  20.     private static NumberMachine instance = new NumberMachine();  
  21.     public static NumberMachine getInstance(){  
  22.         return instance;  
  23.     }  
  24.       
  25.     //取号机的业务可以用线程写在构造器中,意味着一创造出来就不停工作了,也可以在其他类中使用到取号机再写业务  
  26.     //本例放到BankSystem类中开始工作时为取号机指定业务:使用定时器固定频率工作,造成用户比例1:3:6  
  27. }  


ServiceWindow.java

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package blog13Bank;  
  2.   
  3. import java.util.Random;  
  4. import java.util.concurrent.Executors;  
  5.   
  6. //银行的窗口类  
  7. //我自己的思路:写一个模板父类window:提供protected属性和一个抽象的work方法,然后三种窗口为其三种子类,重写其work方法即可  
  8. public class ServiceWindow {  
  9.     private int ID = 1//默认为1号窗口  
  10.     private WindowType type = WindowType.COMMON;//默认为普通窗口  
  11.     //提供属性设置方法,用于创建不同类型的窗口  
  12.     public void setID(int iD) {  
  13.         ID = iD;  
  14.     }  
  15.     public void setType(WindowType type) {  
  16.         this.type = type;  
  17.     }  
  18.       
  19.     //工作业务,线程编写,使其不停的叫号工作。  
  20.     public void work(){  
  21.         Executors.newSingleThreadExecutor().execute(new Runnable(){  
  22.             @Override  
  23.             public void run() {  
  24.                 switch(type){//根据窗口类型不同,有不同的业务处理方式  
  25.                 case COMMON:  
  26.                     while(true){  
  27.                         commonService();                          
  28.                     }  
  29.                 case EXPRESS:  
  30.                     while(true){                          
  31.                         expressService();  
  32.                     }  
  33.                 case VIP:  
  34.                     while(true){                          
  35.                         vipService();  
  36.                     }  
  37.                 }  
  38.             }});  
  39.     }  
  40.       
  41.     //业务流程:窗口叫号  
  42.     public void commonService(){  
  43.         String name = type/*调用枚举的toString*/ + ":第 " + ID + " 号窗口";  
  44.         Integer number = NumberMachine.getInstance().getCommonManager().fetchNumber();  
  45.         System.out.println(name + "开始获取 普通任务");//这个任务种类实际就和number种类也就是NmuberManager对象绑定  
  46.         if(number!=null){//叫号成功,模拟工作,模拟随机工作时间  
  47.             System.out.println(name + "获取 普通任务 成功,"+ name + "正在为第 " + number + " 号 普通客户 服务");  
  48.             int runTime = new Random().nextInt(Constants.RANDOM_FOR_WORK)+1+Constants.MIN_WORK_TIME;  
  49.             try {  
  50.                 Thread.sleep(runTime);  
  51.             } catch (InterruptedException e) {  
  52.                 e.printStackTrace();  
  53.             }  
  54.             System.out.println(name + "为第 " + number + " 号 普通用户 完成服务,共耗时 " + runTime/1000 + " 秒");  
  55.         }else{//叫号失败,没有客户了  
  56.             System.out.println(name + "没有取到 普通任务,空闲一秒...");  
  57.             try {  
  58.                 Thread.sleep(1000);  
  59.             } catch (InterruptedException e) {  
  60.                 e.printStackTrace();  
  61.             }  
  62.         }  
  63.     }  
  64.     public void expressService(){  
  65.         String name = type/*调用枚举的toString*/ + ":第 " + ID + " 号窗口";  
  66.         Integer number = NumberMachine.getInstance().getExpressManager().fetchNumber();  
  67.         System.out.println(name + "开始获取 快速任务");//这个任务种类实际就和number种类也就是NmuberManager对象绑定  
  68.         if(number!=null){//叫号成功,模拟工作,模拟随机工作时间  
  69.             System.out.println(name + "获取 快速任务 成功,"+ name + "正在为第 " + number + " 号 快速客户 服务");  
  70.             int runTime = Constants.MIN_WORK_TIME;  
  71.             try {  
  72.                 Thread.sleep(runTime);  
  73.             } catch (InterruptedException e) {  
  74.                 e.printStackTrace();  
  75.             }  
  76.             System.out.println(name + "为第 " + number + " 号 快速用户 完成服务,共耗时 " + runTime/1000 + " 秒");  
  77.         }else{//叫号失败,没有客户了  
  78.             System.out.println(name + "没有取到 快速任务...");  
  79.             commonService();  
  80.         }  
  81.     }  
  82.     public void vipService(){  
  83.         String name = type/*调用枚举的toString*/ + ":第 " + ID + " 号窗口";  
  84.         Integer number = NumberMachine.getInstance().getVipManager().fetchNumber();  
  85.         System.out.println(name + "开始获取 VIP任务");//这个任务种类实际就和number种类也就是NmuberManager对象绑定  
  86.         if(number!=null){//叫号成功,模拟工作,模拟随机工作时间  
  87.             System.out.println(name + "获取 VIP任务 成功,"+ name + "正在为第 " + number + " 号 VIP客户 服务");  
  88.             int runTime = new Random().nextInt(Constants.RANDOM_FOR_WORK)+1+Constants.MIN_WORK_TIME;  
  89.             try {  
  90.                 Thread.sleep(runTime);  
  91.             } catch (InterruptedException e) {  
  92.                 e.printStackTrace();  
  93.             }  
  94.             System.out.println(name + "为第 " + number + " 号 VIP用户 完成服务,共耗时 " + runTime/1000 + " 秒");  
  95.         }else{//叫号失败,没有客户了  
  96.             System.out.println(name + "没有取到 VIP任务...");  
  97.             commonService();  
  98.         }  
  99.     }  
  100. }  


WindowType.java

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package blog13Bank;  
  2.   
  3. public enum WindowType {  
  4.     COMMON,EXPRESS,VIP;  
  5.       
  6.     @Override  
  7.     public String toString() {  
  8.         String name = null;  
  9.         switch(this){  
  10.         case COMMON:  
  11.             name = "普通";  
  12.             break;  
  13.         case EXPRESS:  
  14.             name = "快速";  
  15.             break;  
  16.         case VIP:  
  17.             name = this.name();  
  18.             break;  
  19.         }  
  20.         return name;  
  21.     }  
  22. }  


Constants.java

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package blog13Bank;  
  2.   
  3. public class Constants {  
  4.     public static int MIN_WORK_TIME = 1000//最小业务办理时限1000毫秒  
  5.     public static int MAX_WORK_TIME = 10000;//最大业务办理时间10000毫秒  
  6.     public static int RANDOM_FOR_WORK = 10000-1000;//业务时间范围  
  7. }  


BankSystem.java

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package blog13Bank;  
  2.   
  3. import java.util.concurrent.Executors;  
  4. import java.util.concurrent.TimeUnit;  
  5.   
  6. public class BankSystem {  
  7.   
  8.     public static void main(String[] args) {  
  9.         //创建6个窗口  
  10.         for(int i=1;i<=4;i++){  
  11.             ServiceWindow window = new ServiceWindow();  
  12.             window.setID(i);  
  13.             window.work();  
  14.         }  
  15.         ServiceWindow window = new ServiceWindow();  
  16.         window.setType(WindowType.EXPRESS);  
  17.         window.work();  
  18.         window = new ServiceWindow();  
  19.         window.setType(WindowType.VIP);  
  20.         window.work();  
  21.           
  22.         //创建NumberMachine对象,因为是单例,不用创对象了,并为之编写业务代码  
  23.         //三个线程产生3种用户  
  24.         Executors.newScheduledThreadPool(1).scheduleAtFixedRate(  
  25.                 new Runnable(){  
  26.                     @Override  
  27.                     public void run() {  
  28.                         Integer number = NumberMachine.getInstance().  
  29.                                 getCommonManager().newCustomer();  
  30.                         System.out.println("第 " + number + " 位普通用户进入大厅,等待服务...");  
  31.                     }  
  32.                 },   
  33.                 0,   
  34.                 1,   
  35.                 TimeUnit.SECONDS);  
  36.           
  37.         Executors.newScheduledThreadPool(1).scheduleAtFixedRate(  
  38.                 new Runnable(){  
  39.                     @Override  
  40.                     public void run() {  
  41.                         Integer number = NumberMachine.getInstance().  
  42.                                 getExpressManager().newCustomer();  
  43.                         System.out.println("第 " + number + " 位快速用户进入大厅,等待服务...");  
  44.                     }  
  45.                 },   
  46.                 0,   
  47.                 3/*快速用户周期为3秒*/,   
  48.                 TimeUnit.SECONDS);  
  49.           
  50.         Executors.newScheduledThreadPool(1).scheduleAtFixedRate(  
  51.                 new Runnable(){  
  52.                     @Override  
  53.                     public void run() {  
  54.                         Integer number = NumberMachine.getInstance().  
  55.                                 getVipManager().newCustomer();  
  56.                         System.out.println("第 " + number + " 位VIP用户进入大厅,等待服务...");  
  57.                     }  
  58.                 },  
  59.                 0,   
  60.                 6/*vip用户周期为6秒*/,   
  61.                 TimeUnit.SECONDS);  
  62.     }  
  63.   
  64. }  

----------- android培训java培训、java学习型技术博客、期待与您交流! ------------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值