学习银行业务调度系统一些理解

来源:互联网 发布:印度赶超中国 知乎 编辑:程序博客网 时间:2024/06/03 18:08


 

 

       学习了银行业务调度系统,我认为除了面向对象的基础意外,要有一个比较重要的知识点就是Java5特性里面的一个线程池,线程的同步和枚举的使用。使用枚举可以很好的判断等候的客户是属于那一类客户、使用线程池和线程的同步可以很好的避免不管客户拿号还是窗口叫号的混乱。

       NumberManager:该类我认为就相当于一个号码管理器一样,用来管理窗口的叫号和不同客户来取号。该类定义一个集合用来存储等待服务的客户号码和上一个客户号码的变量。一个方法是用来拿号一个方法是用来叫号,我们就应该想到,如果这两个方法被同一个线程调用或许出现的问题不大,但是如果被不同的线程调用,可能就会造成拿号跟叫号的混乱,所以,对这两个方法就要进行同步。

                private int lastNumber = 0;
                private List queueNumbers = new ArrayList();
 
                public synchronized Integer generateNewNumber(){
                            queueNumbers.add(++lastNumber);
                            return lastNumber;
                }
                /*
                 * 客户来了,窗口要取号(客户)
                 * 这里返回值为什么不用int而用Integer?
                 * 因为用int,当取号为0的时候就为空,而用Integer会自动装箱和拆箱
                 * 当然这里面用集合的大小来判断,就更不会出现返回值为空的现象
                 */
               public synchronized Integer fetchNumber(){
                       if(queueNumbers.size()>0){
                                return (Integer)queueNumbers.remove(0);
                       }else{
                                return null;
                       }
              }


 

        NumberMachine:主要创建3不同客户(vip、普通、快速)的NumberManager对象的管理器,并实例化。使用get方法返回这3个客户的NumberManager对象。定义一个私有的构造函数,禁止其它类的使用。还要定义一个静态的方法,用来返回该类(NumberManager)的对象,这样可以避免获取客户对象的混乱。

               private NumberManager commonManager = new NumberManager();
               private NumberManager expressManager = new NumberManager();
               private NumberManager vipManager = new NumberManager();

               public NumberManager getCommonManager() {
                        return commonManager;
               }

               public NumberManager getExpressManager() {
                      return expressManager;
               }

              public NumberManager getVipManager() {
                     return vipManager;
              }


        CustomerType:该类是一个枚举类,用来表示三种不同的客户:vip客户(COMMON)、普通客户(EXPRESS)、快速客户(VIP)这三个元素,并重写toString方法,返回元素的相对应的中文名称:比如是EXPRESS返回的中文名称就是“普通”。”

 

         ServiceWindow:从类名上了解就是服务窗口,主要是用来处理一些逻辑上的信息。判读哪个窗口服务哪个一类客户,哪些窗口是空闲的。这里有一点要提的是,因为vip窗口不仅可以为vip客户服务,在没有vip客户空闲的时候,还可以为普通和快速客户服务。所以这一点大家要理解清楚。该类实现了一个start()方法,用来判断来的客户属于哪一种类型的客户。该放实现了一个单个的线程池,线程池里面实现了个run()方法,就是用来判断哪类客户的。

              public void start(){
                        Executors.newSingleThreadExecutor().execute(
                                  new Runnable(){
                                          public void run(){ 
                                                   while(true){
                                                           switch(type){
                                                                  case COMMON:
                                                                          commonService();
                                                                          break;
                                                                  case EXPRESS:
                                                                          expressService();
                                                                          break;
                                                                  case VIP:
                                                                          vipService();
                                                                          break;
                                                           }
                                                    }
                                           }
                                 }
                       );
              }
        在switch里面的case语句都调用的相应的方法。每个方法都基本上的实现了同一个功能,在细节上都稍微有些区别。我就拿普通窗口(commonService())的方法来说,该方法只要是通过NumberMachine的对象来得到号码管理器(NumberManager)窗口要取号的方法fetchNumber()。因为每个窗口服务的时间都有服务的最大值和最小值,通过计算这两个值之间的差值,用一个变量(maxRandom)来接收。在定义一个变量(serviceTime)来接收一个最大的随机值。通过把差值做为参数做为随机数的范围nextInt(maxRandom)+1(随机有可能为0,所以加1就从1到maxRandom)在加上最小的时间Constants.MIN_SERVICE_TIME(该类会在下面见到)。

               private void commonService(){
                        String windowName = "第" + number + "号" + type + "窗口";  
                        System.out.println(windowName + "开始获取普通任务!");
                        Integer serviceNumber = NumberMachine.getInstance().getCommonManager().fetchNumber();  
                        if(serviceNumber != null ){
                                    System.out.println(windowName + "开始为第" + serviceNumber + "号普通客户服务");  
                                    int maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
                                    int serviceTime = new Random().nextInt(maxRandom)+1 + Constants.MIN_SERVICE_TIME;
 
                                    try {
                                             Thread.sleep(serviceTime);
                                    } catch (InterruptedException e) {
                                             e.printStackTrace();
                                    } 
                                   System.out.println(windowName + "完成为第" + serviceNumber + "号普通客户服务,总共耗时" + serviceTime/1000 + "秒");  
                        }else{
                                   System.out.println(windowName + "没有取到普通任务,正在空闲一秒");  
                                   try {
                                             Thread.sleep(1000);
                                   } catch (InterruptedException e) {
                                              e.printStackTrace();
                                   }    
                        }
                }

 

          MainClass:该类是入口类(也可以理解为产生客户类)。该类主要实现功能是:创建不同的服务窗口类,并实例化,还要启动服务窗口线程。

                    for(int i=1;i<5;i++){//创建了4个普通客户
                               ServiceWindow window =  new ServiceWindow();
                               window.setNumber(i);
                               window.start();
                   }
 
                   //创建了1个快速窗口
                    ServiceWindow expressWindow =  new ServiceWindow();
                    expressWindow.setType(CustomerType.EXPRESS);//传入客户的类型
                    expressWindow.start();
  
                   //创建了1个VIP窗口  
                  ServiceWindow vipWindow =  new ServiceWindow();
                  vipWindow.setType(CustomerType.VIP);//传入客户的类型
                  vipWindow.start();
         该类也用到了线程池(也叫定时器,这里的线程池跟ServiceWindow里的线程池是有差别的,大家注意一下就明白了),基本的实现功能也是一样,都是实现客户拿号的功能。我也同样拿普通客户的线程池来说:每一个客户就表示一个线程,所以在newScheduledThreadPool(1)参数里面就参入1。scheduleAtFixedRate()该方法有4个参数,每个参数分别表示:传入一个Runnable线程、过多长时间再来一个客户、以后每隔多长时间在来一个客户、时间的单位是秒。

             //普通客户拿号
             Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
                        new Runnable(){
                                  public void run(){
                                           Integer serviceNumber = NumberMachine.getInstance().getCommonManager().generateNewNumber();                                
                                           System.out.println("第" + serviceNumber + "号普通客户正在等待服务!");      
                                  }
                        },
                       0,//过多长时间再来一个客户
                       Constants.COMMON_CUSTOMER_INTERVAL_TIME, //以后每隔多长时间在来一个客户
                      TimeUnit.SECONDS);//时间的单位是秒

 

         Constants:定义三个常量分别表示最大的时间、最小的时间、多少时间产生一个客户:MAX_SERVICE_TIME、MIN_SERVICE_TIME、COMMON_CUSTOMER_INTERVAL_TIME。这里定义的时间分别是:10000、1000、1

 

 

 

 

 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 沃邮箱改密码短信延迟怎么办 被qq好友拉黑了怎么办 网易邮箱字体变小了怎么办 邮箱注册不了全拼怎么办 家用电器接入两相火线后怎么办 手机充电板坏了怎么办 闪电宝商户乱跳怎么办 网易邮箱发错了怎么办 苹果手机邮件无法连接服务器怎么办 好记星平板电脑开不了机怎么办 邮箱里的文件过期了怎么办 小米手机邮件发不了怎么办 有人加我qq邮箱怎么办 文件太大发邮件太慢怎么办 爱又米发信息怎么办 手机上电子邮件己停止运行怎么办 苹果电子邮件密码忘了怎么办 玩游戏时电脑烫怎么办 qq邮箱独立密码忘记了怎么办 qq邮箱中转站容量不足怎么办 qq邮箱忘记密码了怎么办 qq邮箱超大附件过期怎么办 忘记qq邮箱独立密码怎么办 网易邮箱账号忘了怎么办 微信登录密码忘了怎么办 微信太久没登录登录不上怎么办 邮箱独立密码忘记了怎么办 苹果设置id没有邮箱怎么办 苹果手机设置id没有邮箱怎么办 邮箱的附件过期了怎么办 邮箱里的附件过期了怎么办 邮箱中附件过期了怎么办 扣扣邮箱附件过期怎么办 公司网页版邮箱进不去了怎么办 农行客户端密码忘记了怎么办 中国银行客户端密码忘记了怎么办 建行客户端登录密码忘记了怎么办 中国移动客户端密码忘记了怎么办 再歪一点授权码绑定怎么办 网易邮箱号忘了怎么办 忘记支付宝账号和密码怎么办