• 银行业务调度系统


    1.需求:

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

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

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

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

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

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


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

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

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

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

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

    2.示意图: (- -!原创)

    银行业务调度系统

    3.源代码:

    NumberManager:

    package com.itheima.bankingsystem;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /*号码管理器负责号码的生成和获取(返回)*/
    public class NumberManager {
      private int number=1;//每个号码管理器生成号码都从1开始
      private List<Integer> storeNumbers =new ArrayList<Integer>();
      public synchronized int generateNumber(){//由客户去取生成的号码
          storeNumbers.add(number);
           return number++;
      }
      public synchronized Integer fetchNumber(){//由服务窗口获取号码
          if(storeNumbers.size()!=0)
              return storeNumbers.remove(0);//返回集合中第一个元素,队头元素保证FIFO
          else
             return null;//集合中可能没有元素
      }
     /*窗口的取动作与客户的放动作在操作同一个集合,使用同步,这里的锁为它们对应的 同一个号码管理器实例*/ 
    }

    NumberMachine:

    package com.itheima.bankingsystem;
    /*
     负责统一管理三个号码管理器,NumberMachine在程序运行期间只需要一个实例
    设计成单例.
     */
    public class NumberMachine {
       private NumberManager commonManager=new NumberManager();
       private NumberManager vipManager=new NumberManager();
       private NumberManager expressManager=new NumberManager();
       public NumberManager getCommonManager(){//由于该类只有一个实例,因此成员commonManager的值不变
           return commonManager;               //也就是说多次调用getCommonManager()获取到的是同一个
       }                                       //NumberManager实例,下面同理
       public NumberManager getVIPManager(){
           return vipManager;
       }
       public NumberManager getExpressManager(){
           return expressManager;
       }
       
       /*NumberMachine在程序运行时在内存限制只有一个实例*/
       private NumberMachine(){}
       private static final NumberMachine ref=new NumberMachine();
       public static NumberMachine getInstance(){
           return ref;
       }
    }

    两个枚举:windowType和TimeConstant

    package com.itheima.bankingsystem;
    
    public enum WindowType {
       COMMON,VIP,EXPRESS;
       @Override
       public String toString(){
           switch(this){
               case COMMON: return "普通";
               case VIP: return "VIP";
               case EXPRESS: return "快速";
               default: return null;
           }
       }
    }
    package com.itheima.bankingsystem;
    
    //设置客户办理业务所需时间的最大值和最小值
    public class TimeConstant {
        public static final int MIN_SERVICE_TIME=2;//服务最小时间
        public static final int MAX_SERVICE_TIME=10;//服务最大时间
        
        public static final int COMMON_CUSTOMER_INTERVAL_TIME=1;//每个普通用户来的时间间隔1秒
        public static final int VIP_CUSTOMER_INTERVAL_TIME=6;//每个VIP用户来的时间间隔6秒
        public static final int EXPRESS_CUSTOMER_INTERVAL_TIME=2;//每个快速用户来的时间间隔2秒
    }

    ServiceWindow:

    package com.itheima.bankingsystem;
    
    import java.util.Random;
    import java.util.concurrent.Executors;
    
    public class ServiceWindow {
      private WindowType windowType=WindowType.COMMON;//把三种窗口类型定义成枚举
      private int windowID=1;//窗口的编号 
      public void setType(WindowType windowType) {//通过set方法设置窗口类型和窗口编号进行设置
            this.windowType = windowType;         //而没有通过构造方法在创建对象时传入
      }                                           //这样做可以修改已创建服务窗口对象的ID和type
      public void setWindowID(int windowID) {
            this.windowID = windowID;
      }
      public void start(){//相当于启动了NumberMachine,根据服务的不同
                          //获取不同号码管理器,然后在获取号码
         Executors.newSingleThreadExecutor().execute(
            new Runnable(){
                 @Override
                    public void run(){      
                     while(true){//不断的获取服务窗口不断获取服务(fetchNumber)
                         switch(windowType){
                             case COMMON:commonService();break;
                             case VIP:vipService();break;
                             case EXPRESS:expressService();
                                
                         }
                    }            
                }     
            }     
          ); 
       }
      public void commonService(){
          String windowName=windowID+"号"+windowType+"窗口";               
          Integer serviceNumber=NumberMachine.getInstance().getCommonManager().fetchNumber();//服务窗口开始拿号,为该号客户提供服务  
           System.out.println(windowName+"正在获取任务");         
          if (serviceNumber!=null){
               System.out.println(windowName+"正在为第"+serviceNumber+"个"+"普通客户服务"); 
              
               int minServiceTime=TimeConstant.MIN_SERVICE_TIME;
              int maxServiceTime=TimeConstant.MAX_SERVICE_TIME;
              int serviceTime=new Random().nextInt(maxServiceTime-minServiceTime)+1+minServiceTime;//随机生成2~10秒
              try {
                    Thread.sleep(serviceTime*1000);
                 } catch (InterruptedException e) {
            
                    e.printStackTrace(); 
                 }
              
       
              System.out.println(windowName+"为第"
                            +serviceNumber+"个"+"普通客户服务了"
    //这里没用windowType而固定使用"普通"字符串
                            +serviceTime+"s");    //这是因为例如:在vipService方法中没有vip服务时,会调用commonService
          }                                     //此时this.windowType=VIP,会错误打印VIP客户服务
          else{
              System.out.println(windowName+"窗口没有获取到"+"普通任务休息1秒钟再去获取");
              try {
                    Thread.sleep(1000);//服务窗口休息1秒后再去拿号
               } catch (InterruptedException e) {
                    // TODO 自动生成的 catch 块
                    e.printStackTrace();
               }
          }
      }
      public void vipService(){
            String windowName=windowID+"号"+windowType+"窗口";   
            Integer serviceNumber=NumberMachine.getInstance().getVIPManager().fetchNumber();//服务窗口开始拿号,为该号客户提供服务  
            System.out.println(windowName+"正在获取任务");   
             
              if (serviceNumber!=null){//取到number,开始服务
                  System.out.println(windowName+"正在为第"+serviceNumber+"个"+windowType+"客户服务"); 
                   int minServiceTime=TimeConstant.MIN_SERVICE_TIME;
                  int maxServiceTime=TimeConstant.MAX_SERVICE_TIME;
                  int serviceTime=new Random().nextInt(maxServiceTime-minServiceTime)+1+minServiceTime;//随机生成2~10秒
                  try {
                        Thread.sleep(serviceTime*1000);
                     } catch (InterruptedException e) {
                        // TODO 自动生成的 catch 块
                        e.printStackTrace();
                     }
                  
              
                  System.out.println(windowName+"为第"
                          +serviceNumber+"个"+windowType+"客户服务了" 
                              +serviceTime+"s");
              }    
              else{
                  System.out.println(windowName+"窗口没有获取到"+windowType+"任务");
                  commonService();//VIP窗口没有获取到VIP任务,获取普通任务去服务,直接调用了 commonService(),去普通任务集合去取
              }
      }
      public void expressService(){
             String windowName=windowID+"号"+windowType+"窗口";   
             Integer serviceNumber=NumberMachine.getInstance().getExpressManager().fetchNumber();//服务窗口开始拿号,为该号客户提供服务  
             System.out.println(windowName+"正在获取任务");   
              if (serviceNumber!=null){//取到number,开始服务
                  System.out.println(windowName+"正在为第"+serviceNumber+"个"+windowType+"客户服务");
                
                  
                  int serviceTime=TimeConstant.MIN_SERVICE_TIME;
                
                  try {
                        Thread.sleep(serviceTime*1000);
                     } catch (InterruptedException e) {
                        // TODO 自动生成的 catch 块
                        e.printStackTrace();
                     }
                  
                
                  System.out.println(windowName+"为第"
                                +serviceNumber+"个"+windowType+"客户服务了" 
                                +serviceTime+"s");
              }    
              else{
                  System.out.println(windowName+"窗口没有获取到"+windowType+"任务");
                  commonService();//express窗口没有获取到express任务,获取普通任务去服务,直接调用了 commonService()
              }
       }
    }

    MainClass:

    package com.itheima.bankingsystem;
    
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    
    public class MainClass {
      public static void main(String[] args){
         /*创建六个窗口对象(,1个VIP窗口,1个快速窗口)*/
          //4个普通窗口
          for(int i=1;i<5;++i){
             ServiceWindow commonWindow=new ServiceWindow();
             commonWindow.setWindowID(i);
             commonWindow.start();//开启服务
          }
          //1个VIP窗口 
          ServiceWindow vipWindow=new ServiceWindow();
          vipWindow.setType(WindowType.VIP);
          vipWindow.setWindowID(6);
          vipWindow.start();
          //1个快速窗口
         ServiceWindow expressWindow=new ServiceWindow();
          expressWindow.setType(WindowType.EXPRESS); 
          expressWindow.setWindowID(5);
          expressWindow.start();
         
          /*
             模拟客户来取 
          VIP客户 :普通客户 :快速客户  =  1 :6 :3
            这个比例通过计时器来完成,假设每隔1秒来一个普通客户,每隔2秒来来一个快速客户.  
          ,每隔六秒来一个VIP客户.
            假设程序运行了12秒,来了12(12/1)个普通客户,6个快速客户(12/2),2个VIP客户(12/6)
           2:12:6=1:6:3;
          */
          Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
                  new Runnable(){
                      @Override 
                      public void run(){
                        int number=NumberMachine.getInstance().getCommonManager().generateNumber();
                        System.out.println("第"+number+"号普通客户等待服务");
                      }
                  },
                  1,
                  TimeConstant.COMMON_CUSTOMER_INTERVAL_TIME, 
                  TimeUnit.SECONDS);
          Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
                  new Runnable(){
                      @Override 
                      public void run(){
                          int number=NumberMachine.getInstance().getVIPManager().generateNumber();
                          System.out.println("第"+number+"号VIP客户等待服务");
                      }
                  },
                  1,
                  TimeConstant.VIP_CUSTOMER_INTERVAL_TIME, 
                  TimeUnit.SECONDS);
                           
         Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
                  new Runnable(){
                      @Override 
                      public void run(){
                          int number=NumberMachine.getInstance().getExpressManager().generateNumber();
                          System.out.println("第"+number+"号快速客户等待服务");
                      }
                  },
                  1,
                  TimeConstant.EXPRESS_CUSTOMER_INTERVAL_TIME, 
                  TimeUnit.SECONDS);
                    
      }
    }

    运行结果

    运行结果可以通过输出到文本方式测试.

    3.用模板方法设计模式改写ServiceWindow:

    package com.itheima.bankingsystem;
    
    import java.util.Random;
    import java.util.concurrent.Executors;
    
    public class ServiceWindowNewCode {
      private WindowType windowType=WindowType.COMMON;
      private int windowID=1;//窗口的编号 
      String windowName=windowID+"号"+windowType+"窗口";
      public void setType(WindowType windowType) {
            this.windowType = windowType;         
      }                                          
      public void setWindowID(int windowID) {
            this.windowID = windowID;
      }
      public void start(){
         Executors.newSingleThreadExecutor().execute(
            new Runnable(){
                 @Override
                    public void run(){      
                     while(true){
                         Service();//默认为:普通窗口
                    }            
                }     
            }     
          ); 
       }
     
      public void Service(){
          
          Integer serviceNumber=getServiceNumber();//不同的窗口对象会使用各自复写的getServiceNumber()方法(多态)
           System.out.println(windowName+"正在获取任务");         
          if (serviceNumber!=null){
               System.out.println(windowName+"正在为第"+serviceNumber+"个"+"普通客户服务"); 
       
              long serviceTime=getServiceTime();
              
              try {
                    Thread.sleep(serviceTime);
                 } catch (InterruptedException e) {
            
                    e.printStackTrace(); 
                 }
            }                                  
          else
              notTakeTaskNext();
      }
     
      /*不同类型的客户需要从不同的号码管理器获取ServiceNumber*/
      protected int getServiceNumber(){
         return NumberMachine.getInstance().getCommonManager().fetchNumber();
         
      }
      /*VIP和COMMON服务时间在同一个范围内,EXPRESS为最小值*/
      protected long getServiceTime(){
          int minServiceTime=TimeConstant.MIN_SERVICE_TIME;
          int maxServiceTime=TimeConstant.MAX_SERVICE_TIME;
          int serviceTime=new Random().nextInt(maxServiceTime-minServiceTime)+1+minServiceTime;//随机生成2~10秒
          return serviceTime*1000;
      }
      /*打印出哪个窗口正在为那个客户服务*/
      protected void printServiceCustomer(){
          System.out.println(windowName+"正在为第"+getServiceNumber()+"个"+"普通客户服务"); 
      }
      /*打印服务了多长时间*/
      protected void printServiceTime(){
           System.out.println(windowName+"为第"
                   +getServiceNumber()+"个"+"普通客户服务了" 
                   +getServiceTime()+"s"); 
      }
      /*窗口未取到任务需要干的事*/
      protected void notTakeTaskNext(){
          System.out.println(windowName+"窗口没有获取到"+"普通任务休息1秒钟再去获取");
          try {
                Thread.sleep(1000);//服务窗口休息1秒后再去拿号
           } catch (InterruptedException e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
           }
      }
    }

    VIPServiceWindow

    class VIPServiceWindow extends ServiceWindowNewCode{
        private  WindowType windowType=WindowType.VIP;//把三种窗口类型定义成枚举
        protected int getServiceNumber(){//复写
          return NumberMachine.getInstance().getVIPManager().fetchNumber();
                 
        }
        protected void printServiceTime(){
               System.out.println(windowName+"为第"
                       +getServiceNumber()+"个"+windowType+"客户服务了" 
                       +getServiceTime()+"s"); 
         }
        protected void notTakeTaskNext(){//复写
             System.out.println(windowName+"窗口没有获取到"+windowType+"任务");
              new ServiceWindowNewCode().Service();//必须通过对象来调用普通窗口服务
        }
    }

    ExpressServiceWindow

    class ExpressServiceWindow extends ServiceWindowNewCode{
        private WindowType windowType=WindowType.EXPRESS;
        protected int getServiceNumber(){//复写
              return NumberMachine.getInstance().getExpressManager().fetchNumber();
                     
        }
        protected long getServiceTime(){
             return TimeConstant.MIN_SERVICE_TIME;
          }
        protected void printServiceTime(){
               System.out.println(windowName+"为第"
                       +getServiceNumber()+"个"+windowType+"客户服务了" 
                       +getServiceTime()+"s"); 
         }
        protected void notTakeTaskNext(){//复写
            System.out.println(windowName+"窗口没有获取到"+windowType+"任务");
             new ServiceWindowNewCode().Service();//必须通过对象来调用普通窗口服务
       }
    }
  • 相关阅读:
    堆排序算法(C#实现)
    在 .NET 2.0 中享受 .NET 3.0的特性
    火花:使用文件管理功能管理我的连接
    我们可以做的更好
    有价值的文章
    网上掏宝
    WPF绑定技术一步步学
    结构类型需要重载GetHashCode和Equals
    关于扩展Visual Studio 2005的相关资料
    插件模型应该考虑的问题
  • 原文地址:https://www.cnblogs.com/yiqiu2324/p/3253962.html
Copyright © 2020-2023  润新知