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

-------  android培训、 java培训、期待与您交流! ----------

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

银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。
有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。
异步随机生成各种类型的客户,生成各类型用户的概率比例为:
        VIP客户 :普通客户 :快速客户  =  1 :6 :3。
客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需的时间,快速客户办理业务所需时间为最小值(提示:办理业务的过程可通过线程Sleep的方式模拟)。
各类型客户在其对应窗口按顺序依次办理业务。
当VIP(6号)窗口和快速业务(5号)窗口没有客户等待办理业务的时候,这两个窗口可以处理普通客户的业务,而一旦有对应的客户等待办理业务的时候,则优先处理对应客户的业务。
随机生成客户时间间隔以及业务办理时间最大值和最小值自定,可以设置。
不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。 

每个客户由银行的一个取号机产生,于是就有一个号码管理器NumberManager对象,让这个对象不断的产生号码,就等于随机生成了客户.

三个号码管理器对象统一由一个号码机器NumberMachine进行管理号码机器设计成单例

客户依次办理业务其实是窗户依次叫号.是服务窗口ServiceWindow依次找号码管理器 获取当前的服务的号码.

wKioL1QIAGjQyl-FAADxPFIUy9Q776.jpg

int maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;

int serviceTime = new Random().nextInt(maxRandom)+1 + Constants.MIN_SERVICE_TIME;

//0~8999    1~9000  1001~10000

我改为了int serviceTime = (new Random().nextInt(Constants.MAX_SERVICE_TIME/1000)+1)*Constants.MIN_SERVICE_TIME;

1~10   1000~10000

NumberManager类的编写

     号码管理器可以进行号码的增加和取出号码, 模拟的过程是不同客户的到达和为窗口服务 , 给窗口取排队的号码.

package cn.likai.bank;

import java.util.LinkedList;

public class NumberManager {
      private int lastNumber = 1;
      private LinkedList<Integer> queue = new LinkedList<Integer>();
     
      //为客户服务,增加一个号码
      public synchronized Integer generateNewManager(){
           //新增元素存入队列
           queue.addLast( lastNumber );
           return lastNumber ++;
     }
     
      //为窗口服务 , 给窗口取排队的号码
      public synchronized Integer fetchServiceNumber(){
          Integer number = null ;
           if (queue .size()>0)
              number = queue.pollFirst();
           return number;
     }
}

NumberManager类的编写

    取号机,统管三个不同客户号码管理器,并将构造函数私有化,外界只有调用获得实例的函数获取三个成员变量,编写还是比较简单的.

package cn.likai.bank;

//取号机,统管三个不同客户号码管理器
public class NumberMachine {
      private final static NumberMachine instance = new NumberMachine();
      private NumberManager CommonManager = new NumberManager();
      private NumberManager VIPManager = new NumberManager();
      private NumberManager ExpressManager = new NumberManager();
     
      //构造方法私有化
      private NumberMachine(){}
     
      public NumberManager getCommonManager() {
           return CommonManager ;
     }
      public NumberManager getVIPManager() {
           return VIPManager ;
     }
      public NumberManager getExpressManager() {
           return ExpressManager ;
     }    
     
      public static NumberMachine getInstance(){
           return instance ;
     }    

}

Contants接口的编写

     因为服务窗口要用的几个时间的值,将其抽取出Contants接口定义为常量, 利于理解.

package cn.likai.bank;

public interface Constants {
      //最长服务时间10S
      int MAX_SERVICE_TIME = 10000;
      //最短服务时间1S
      int MIN_SERVICE_TIME = 1000; 
     
      int COMMON_CUSTOMER_INTERVAL_TIME = 1;
}
用的的枚举类
package cn.likai.bank;

public enum CustomerType {
      COMMON, EXPRESS ,VIP ;
     
      public String toString(){
           //枚举变量也能用于switch语句
           switch (this ){
               case COMMON : return "普通客户";
               case EXPRESS : return "快速客户";
               case VIP : return "VIP客户";
               default : return null;
          }
     }
}

ServiceWindows类的编写

     服务窗口分为三种类型,前面已由枚举定义过了.每个服务窗口的标志就是窗口的类型和ID号. 根据ID的不同从而影响到服务不同的人群. 快速窗口和VIP窗口可以在没有本类型客户服务的时候为普通客户服务.

package cn.likai.bank;

import java.util.Random;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class ServiceWindow {
      private CustomerType type = CustomerType .COMMON ;
      private int windowID = 1;    
     
      public void setType(CustomerType type) {
           this .type = type;
     }
      public void setWindowID( int windowID) {
           this .windowID = windowID;
     }
     
      public void start(){
           //只需要一个线程,在线程池中放入一个线程.线程池从中找出一个线程,是线程池去执行任务
          Executor e = Executors.newSingleThreadExecutor();
          e.execute( new Runnable(){
               public void run(){
                    while (true ){
                         switch (type ){
                              case COMMON :
                                  commonService(); break ;
                              case EXPRESS :
                                  expressService(); break ;                             
                              case VIP :
                                  VIPService(); break ;
                        }
                   }
              }
          });           
     }    
     
      public void commonService(){
          String windowName = "第" + windowID + "号" +type +"窗口" ;
          System. out .println(windowName + "开始获取普通任务!" );
          Integer serviceNumber = NumberMachine.getInstance().getCommonManager().fetchServiceNumber();
           //不为空表示有人在排队,可以为其服务
           if (serviceNumber != null){
              System. out .println(windowName + "开始为第" + serviceNumber + "号普通客户服务" );
               long beginTime = System.currentTimeMillis();                
               int serviceTime = ( newRandom().nextInt(Constants.MAX_SERVICE_TIME /1000)+1)*Constants. MIN_SERVICE_TIME;
               try {
                   Thread. sleep(serviceTime);
              } catch (Exception e){
                   e.printStackTrace();
              }    
               long costTime = System.currentTimeMillis()-beginTime;
              System. out .println(windowName + "完成为第" + serviceNumber + "号普通客户服务,耗时" + costTime/1000 + "秒" );      
          } else {
              System. out .println(windowName+"没有取到普通任务,休息一秒" );
               try {
                   Thread. sleep(1000);
              } catch (Exception e){
                   e.printStackTrace();
              }
          }         
     }    
     
      public void expressService(){
          String windowName = "第" + windowID + "号" + type + "窗口" ;
          System. out .println(windowName + "开始获取快速任务!" );
          Integer serviceNumber = NumberMachine.getInstance().getCommonManager().fetchServiceNumber();
           //不为空表示有人在排队
           if (serviceNumber != null){
              System. out .println(windowName + "开始为第" + serviceNumber + "号快速客户服务" );  
               long beginTime = System.currentTimeMillis();  
               try {
                   Thread. sleep(Constants. MIN_SERVICE_TIME);
              } catch (Exception e){
                   e.printStackTrace();
              }    
               long costTime = System.currentTimeMillis()-beginTime;
              System. out .println(windowName + "完成为第" + serviceNumber + "号快速客户服务,耗时" + costTime/1000 + "秒" );      
          } else {
              System. out .println(windowName + "没有取到快速任务!" );                  
              commonService();
          }             
     }

      public void VIPService(){
          String windowName = "第" + windowID + "号" + type + "窗口" ;
          System. out .println(windowName + "开始获取VIP任务!" );
          Integer serviceNumber = NumberMachine.getInstance().getCommonManager().fetchServiceNumber();
           //不为空表示有人在排队
           if (serviceNumber != null){
              System. out .println(windowName + "开始为第" + serviceNumber + "号VIP客户服务" );   
               long beginTime = System.currentTimeMillis();  
               try {
                   Thread. sleep(Constants. MIN_SERVICE_TIME);
              } catch (Exception e){
                   e.printStackTrace();
              }    
               long costTime = System.currentTimeMillis()-beginTime;
              System. out .println(windowName + "完成为第" + serviceNumber + "号VIP客户服务,耗时" + costTime/1000 + "秒");         
          } else {
              System. out .println(windowName + "没有取到VIP任务!" );                 
              commonService();
          }                  
     }
}

MainClass类的编写

     分别创建4个普通窗口,1个快速窗口,一个VIP窗口并开启服务功能. 再实例化一个取号机,共包含三个区号器,分别加载普通,快速和VIP客户.这样达到了一边增加,一边消耗的目的,从而完成了该系统.

package cn.likai.bank;

import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class MainClass {

      public static void main(String[] args) {   
           for (int i=1;i<5;i++){
              ServiceWindow commonWindow = new ServiceWindow();
              commonWindow.setWindowID(i);
              commonWindow.start();
          }
          
          ServiceWindow VIPWindow = new ServiceWindow();
          VIPWindow.setType( CustomerType. VIP);
          VIPWindow.start();
          
          ServiceWindow expressWindow = new ServiceWindow();
          expressWindow.setType( CustomerType. EXPRESS);
          expressWindow.start();
          
          
           //模拟三类用户不停取号,按1:3:6
          Executors. newScheduledThreadPool(1).scheduleAtFixedRate(
                    new Runnable(){
                         public void run(){
                             Integer number = NumberMachine.getInstance().getCommonManager().generateNewManager();
                             System. out .println(number+"号普通客户等待服务" );
                        }
                   }, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME *1, TimeUnit.SECONDS );
          
          Executors. newScheduledThreadPool(1).scheduleAtFixedRate(
                    new Runnable(){
                         public void run(){
                             Integer number = NumberMachine.getInstance().getExpressManager().generateNewManager();
                             System. out .println(number+"号快速客户等待服务" );
                        }
                   }, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME *3, TimeUnit.SECONDS );
          
          Executors. newScheduledThreadPool(1).scheduleAtFixedRate(
                    new Runnable(){
                         public void run(){
                             Integer number = NumberMachine.getInstance().getVIPManager().generateNewManager();
                             System. out .println(number+"号VIP客户等待服务" );
                        }
                   }, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME *6, TimeUnit.SECONDS );      
     }
     
}


打印结果:

第1号普通客户窗口开始获取普通任务!
第1号普通客户窗口没有取到普通任务,休息一秒
第3号普通客户窗口开始获取普通任务!
第3号普通客户窗口没有取到普通任务,休息一秒
第1号VIP客户窗口开始获取VIP任务!
第1号VIP客户窗口没有取到VIP任务!
第1号VIP客户窗口开始获取普通任务!
第1号VIP客户窗口没有取到普通任务,休息一秒
第2号普通客户窗口开始获取普通任务!
第2号普通客户窗口没有取到普通任务,休息一秒
第4号普通客户窗口开始获取普通任务!
第4号普通客户窗口没有取到普通任务,休息一秒
第1号快速客户窗口开始获取快速任务!
第1号快速客户窗口没有取到快速任务!
第1号快速客户窗口开始获取普通任务!
第1号快速客户窗口没有取到普通任务,休息一秒
1号普通客户等待服务
1号快速客户等待服务
1号VIP客户等待服务
第1号普通客户窗口开始获取普通任务!
第1号普通客户窗口开始为第1号普通客户服务
第4号普通客户窗口开始获取普通任务!
第4号普通客户窗口没有取到普通任务,休息一秒
第2号普通客户窗口开始获取普通任务!
第2号普通客户窗口没有取到普通任务,休息一秒
第1号VIP客户窗口开始获取VIP任务!
第1号VIP客户窗口没有取到VIP任务!
第1号VIP客户窗口开始获取普通任务!
第1号VIP客户窗口没有取到普通任务,休息一秒
第1号快速客户窗口开始获取快速任务!
第1号快速客户窗口没有取到快速任务!
第1号快速客户窗口开始获取普通任务!
第1号快速客户窗口没有取到普通任务,休息一秒
第3号普通客户窗口开始获取普通任务!
第3号普通客户窗口没有取到普通任务,休息一秒
2号普通客户等待服务
第4号普通客户窗口开始获取普通任务!
第4号普通客户窗口开始为第2号普通客户服务
第2号普通客户窗口开始获取普通任务!
第2号普通客户窗口没有取到普通任务,休息一秒
第1号快速客户窗口开始获取快速任务!
第1号快速客户窗口没有取到快速任务!
第1号快速客户窗口开始获取普通任务!
第1号快速客户窗口没有取到普通任务,休息一秒
第1号VIP客户窗口开始获取VIP任务!
第1号VIP客户窗口没有取到VIP任务!
第1号VIP客户窗口开始获取普通任务!
第1号VIP客户窗口没有取到普通任务,休息一秒
3号普通客户等待服务
第3号普通客户窗口开始获取普通任务!
第3号普通客户窗口开始为第3号普通客户服务
第2号普通客户窗口开始获取普通任务!
第2号普通客户窗口没有取到普通任务,休息一秒
第4号普通客户窗口完成为第2号普通客户服务,耗时1秒
.......
.......

你可能感兴趣的:(android,程序员,java培训)