银行业务调度

来源:互联网 发布:淘宝与阿里巴巴的关系 编辑:程序博客网 时间:2024/05/29 04:27


张孝祥老师7k面试题之银行业务调度:


这道题还是有些难度的,不过一步一步分析,也不那么难理解,本片博客重点说说思路:

 

一.需求分析:

(1)银行内有6个业务窗口, 4个普通窗口,1快速窗口,1个VIP窗口。

(2)有三种对应类型的客户:VIP客户,普通客户,快速客户。
(3)VIP客户以及普通客户办理业务所需的时间有最大值和最小值,快速客户办理业务所需时间为最小值,三种客户比例为VIP客户:普通客户 :快速客户  =  1 :6 :3。
(4)当VIP窗口和快速窗口没有客户等待可以为普通客户服务
 
二.用面相对象的思想可以提炼出三个对象,
1.银行窗口,
2.号码生成器(可以生成三种对应类型的客户的号码),
3.号码管理器(生成号码和获取窗口马上要服务的号码)
 
三.整个流程可这样设计:
 
1.号码管理器产生新号码,并对外提供获取窗口马上要办理的号码的方法。
2.号码生成器,由于只想它在内存中只有一个对象,采用单例设计,并在里面定义3个指向号码管理器的属性对象,分别表示普通客户,快速客户,vip客户。并对外提供访问对象的的方法。
3.开启一个线程循环调用3种窗口那类型,线程种根据不同客户,调用不同的窗口,用executors线程池。可以有switch() case :去判断怎么调用。类型这个变量只有3种考虑用枚举去定义。用if()else()去判断该类型窗口有没有等待的服务的号码,如果是快速窗口和vip窗口没有等待的,就为普通窗口服务。
 
4.主函数:创建6个窗口,并定于3个定时器,分别去创建新的普通号码,新的快速号码,新的vip号码。(定时器用execoutor接口创建)
 
四 .具体步骤:
1.  创建号码管理器类:
(1)  定义一个变量记录上一个客户的号码,方便得道下一个客户号码。
(2)  定义一个集合,存储在排队的号码。
(3)  定义一个方法可以产生新的号码。
(4)  定义一个方法能够给窗口提供马上要服务的号码。
  (面相对象的思想:谁拥有数据谁对外提供方法。)
代码体现:
public class NumberManager {/*步骤:1定义一个变量记录上一个生成了多少号,方便给下一个多少号。2定义一个集合来装还没有服务的号 *    3创建取号的方法,4创建个给窗口多少号的方法。* *    说明3,4是不同线程操作相同 的数据需要同步*/       private int lastNumber=0;      private  List< Integer>  queueNumbers = new ArrayList<Integer>();            //定义方法生成号码      public synchronized Integer shengChengNumber(){           queueNumbers.add(++lastNumber);      return lastNumber;      }      //为窗口获取号码      public synchronized Integer quChuNumber(){           if(queueNumbers.size()>0){           return queueNumbers.remove(0);           }else{            return null;      }      }}

(注意:不同线程操作共享资源,需要加锁。)

2.  号码生成器由于只想它在内存中只有一个对象,采用单例设计,并在里面定义3个指向号码管理器的属性对象,分别表示普通客户,快速客户,vip客户。并对外提供访问对象的的方法。

(1)  单例设计号码管理器类

(2)  定义3个属性对象

提供方法返回号码管理器对像。

public class Numbermachne {/*号码管理器:1.定义变量指向numbermanager对象,分别表示普通,快速,vip。 *       2定义3个方法返回3个对象 *     3   把号码管理器设为单例*///用单例设计,让号码管理器的对象只有一个。private Numbermachne (){};private static Numbermachne instance = new Numbermachne();public static Numbermachne getinstance(){return instance;}//创建三个属性,分别表示普通客服,快速客服,vip客服。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;}}

3, (1)定义3种客服窗口的枚举:

        (2)开启一个线程,循环调用不同的服务窗口(需要使用executors线程池)

        (3)如果快速窗口和vip窗口没有服务的号码,调用普通窗口的服务。

public enum Customer {COMMON,EXPRESS,VIP;public String toString(){String name = null;switch (this) {case COMMON:name="普通客服";break;case EXPRESS:name="快速客服";break;case VIP:name="VIP客服";break;}return name;}public class ServiceWindow {      private static Logger logger = Logger.getLogger("cn.itcast.bankqueue");      private Customer type = Customer.COMMON;      private int number = 1;        public Customer getType() {          return type;      }        public void setType(Customer type) {          this.type = type;      }            public void setNumber(int number){          this.number = number;      }            public void start(){          Executors.newSingleThreadExecutor().execute(                  new Runnable(){                      public void run(){                          //下面这种写法的运行效率低,最好是把while放在case下面                          while(true){                              switch(type){                                  case COMMON:                                      commonService();                                      break;                                  case EXPRESS:                                      expressService();                                      break;                                  case VIP:                                      vipService();                                      break;                              }                          }                      }                  }          );      }            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();              }                         }      }            private void expressService(){          Integer serviceNumber = NumberMachine.getInstance().getExpressManager().fetchNumber();          String windowName = "第" + number + "号" + type + "窗口";             System.out.println(windowName + "开始获取快速任务!");                 if(serviceNumber !=null){              System.out.println(windowName + "开始为第" + serviceNumber + "号快速客户服务");                          int serviceTime = 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 + "没有取到快速任务!");                             commonService();          }      }            private void vipService(){            Integer serviceNumber = NumberMachine.getInstance().getVipManager().fetchNumber();          String windowName = "第" + number + "号" + type + "窗口";             System.out.println(windowName + "开始获取VIP任务!");                    if(serviceNumber !=null){              System.out.println(windowName + "开始为第" + serviceNumber + "号VIP客户服务");                         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 + "号VIP客户服务,总共耗时" + serviceTime/1000 + "秒");               }else{              System.out.println(windowName + "没有取到VIP任务!");                            commonService();          }         }  }  }


4主函数:(1)创建窗口对象,4个普通窗口,1个快速窗口,1个vip窗口

         (2)创建3个定时期,定时创建普通号码,快速号码,vip号码。

public class MainClass {          private static Logger logger = Logger.getLogger("cn.itcast.bankqueue");              public static void main(String[] args) {          //产生4个普通窗口          for(int i=1;i<5;i++){              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();                          //普通客户拿号          Executors.newScheduledThreadPool(1).scheduleAtFixedRate(                  new Runnable(){                      public void run(){                          Integer serviceNumber = NumberMachine.getInstance().getCommonManager().generateNewNumber();                          /**                           * 采用logger方式,无法看到直观的运行效果,因为logger.log方法内部并不是直接把内容打印出出来,                           * 而是交给内部的一个线程去处理,所以,打印出来的结果在时间顺序上看起来很混乱。                           */                          //logger.info("第" + serviceNumber + "号普通客户正在等待服务!");                          System.out.println("第" + serviceNumber + "号普通客户正在等待服务!");                                             }                  },                  0,                  Constants.COMMON_CUSTOMER_INTERVAL_TIME,                   TimeUnit.SECONDS);                    //快速客户拿号          Executors.newScheduledThreadPool(1).scheduleAtFixedRate(                  new Runnable(){                      public void run(){                          Integer serviceNumber = NumberMachine.getInstance().getExpressManager().generateNewNumber();                          System.out.println("第" + serviceNumber + "号快速客户正在等待服务!");                      }                  },                  0,                  Constants.COMMON_CUSTOMER_INTERVAL_TIME * 2,                   TimeUnit.SECONDS);                    //VIP客户拿号          Executors.newScheduledThreadPool(1).scheduleAtFixedRate(                  new Runnable(){                      public void run(){                          Integer serviceNumber = NumberMachine.getInstance().getVipManager().generateNewNumber();                          System.out.println("第" + serviceNumber + "号VIP客户正在等待服务!");                      }                  },                  0,                  Constants.COMMON_CUSTOMER_INTERVAL_TIME * 6,                   TimeUnit.SECONDS);      }  }


0 0
原创粉丝点击