银行业务调度系统

1、项目需求:

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

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

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

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

        VIP客户:普通客户:快速客户  =  163

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

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

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

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

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

 


2、面向对象的分析与设计

有三种对应类型的客户:VIP客户,普通客户,快速客户,异步随机生成各种类型的客户,各类型客户在其对应窗口按顺序依次办理业务。

   Ø  在银行办理业务时,每一个客户其实就是由银行的一个取号机器以产生号码的方式来表示的,所以此项目中需要有一个号码管理器的对象,让这个对象不断的产生号码,就等于是随机生成了客户。


   Ø  由于有三种类型的客户,每类客户的号码编排都是完全独立的,所以本银行业务调度系统一共要产生三个号码管理器对象,各自管理一类用户的排队号码,这三个号码管理器对象统一由一个号码机器进行管理。这个号码机器在整个系统中始终只能有一个,所以它要被设计成单例。


各类型客户在其对应窗口按顺序依次办理业务,准确地说,应该是窗口依次叫号。

问题:每个窗口怎么知道该叫哪一个号码呢?

答:窗口一定是问的相应的号码管理器,即服务窗口每次找号码管理器获取当前要被服务的号码。


类图(便于分析和理解)


NumberManager类:

     1)定义一个用于存储上一个客户号码的成员变量和用于存储所有等待服务的客户号码的队列集合。

     2)定义一个产生新号码的方法和获取马上要为之服务的号码的方法,这两个方法被不同的线程操作了相同的数据,所以要进行同步。


NumberMachine类:

     1)定义三个成员变量分别指向三个NumberManager对象,分别表示普通、快速、VIP客户的号码管理器,定义三个对应的方法来返回这三个NumberManager对象。

     2)将NumberMachine类设计成单例设计模式。


ServiceWindow类:

     1)定义一个start()方法,内部启动一个线程,根据服务窗口的类别分别循环调用三个不同的方法。

     2)定义三个方法分别对三种客户进行服务,为了观察运行效果,应详细打印出其中的细节信息。


CustomerTyper枚举类:

     1)系统中有三种类型的客户,所以用定义一个枚举类,其中定义三个成员分别表示三种类型的客户。

     2)重写toString()方法,返回类型的中文名称。(这是在后面编码时重构出来的,刚开始不用考虑)


MainClass类:

     1)用for循环创建出4个普通窗口,再创建出1个快速窗口和1个VIP窗口。

     2)接着再创建三个定时器,分别定时去创建新的普通客户号码、新的快速客户号码、新的VIP客户号码。

 

Constants类:

     定义三个变量:MAX_SERVICE_TIME、MIN_SERVICE_TIME和COMMON_CUSTOMER_INTERVAL_TIME

 


3、实现代码:

NumberManager.java

package com.isoftstone.interview.bank;
 
import java.util.ArrayList;
import java.util.List;
 
public class NumberManager {
   //定义用于存储上一个客户号码的成员变量lastNumber。
   private int lastNumber = 0;
   //用于存储所有等待服务的客户号码的集合队列queueNumber。
   private List<Integer> queueNumber = new ArrayList<Integer>();
  
   //用于产生新号码的方法generateNewManager。
   public synchronized Integer generateNewManager(){
      queueNumber.add(++lastNumber);
      return lastNumber;
   }
  
   //获取马上要为之服务的号码的方法fetchServiceNumber。
   public synchronized Integer fetchServiceNumber(){
      if(queueNumber.size() > 0){
         return queueNumber.remove(0);
      }else{
         return null;
      }
   }
}

NumberMachine.java

package com.isoftstone.interview.bank;

public classNumberMachine {
   //普通客户号码管理器
   private NumberManager commonManager = new NumberManager();
   //快速客户号码管理器
   private NumberManager expressManager = new NumberManager();
   //VIP客户号码管理器
   private NumberManager vipManager = new NumberManager();
  
   //获取普通客户号码管理器对象的方法。
   public NumberManager getCommonManager() {
      return commonManager;
   }
   //获取快速客户号码管理器对象的方法。
   public NumberManager getExpressManager() {
      return expressManager;
   }
   //获取VIP客户号码管理器对象的方法。
   public NumberManager getVipManager() {
      return vipManager;
   }
  
   //私有化空参数构造方法,禁止外部其它类创建本类对象。
   private NumberMachine(){}
   //将本类设计成单例设计模式,在本类内部创建好本类对象。
   private static NumberMachine instance = new NumberMachine();
   //对外提供唯一使用本类对象的静态方法。
   public static NumberMachine getInstance(){
      return instance;
   } 
}

ServiceWindow.java

package com.isoftstone.interview.bank;

import java.util.Random;
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;
   }
  
   //定义start方法启动一个线程。
   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;
                }
            }
         }
      });
   }
  
   //普通客户窗口服务。
   private void commonService() {
      String windowName = "第"+windowId+"号"+type+"窗口";
      Integer number = NumberMachine.getInstance().getCommonManager().fetchServiceNumber();
      System.out.println(windowName+"正在获取普通任务...");
      if(number != null){
         System.out.println(windowName+"开始为第"+number+"号普通客户服务");
         long beginTime = System.currentTimeMillis();
         int maxRand = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
         long serverTime = new Random().nextInt(maxRand)+1+Constants.MIN_SERVICE_TIME;
         try {
            Thread.sleep(serverTime);
         }catch(InterruptedException e) {
            e.printStackTrace();
         }
         long costTime = System.currentTimeMillis() - beginTime;
         System.out.println(windowName+"完成为第"+number+"号普通客户服务,总共耗时"+(costTime/1000)+"秒");
      }
      else{
         System.out.println(windowName+"没有取到普通任务,正在空闲1秒钟!");
         try {
            Thread.sleep(1000);
         }catch(InterruptedException e) {
            e.printStackTrace();
         }
      }
   }
  
   //快速客户窗口服务。
   private void expressService() {
      String windowName = "第"+windowId+"号"+type+"窗口";
      Integer number = NumberMachine.getInstance().getExpressManager().fetchServiceNumber();
      System.out.println(windowName+"正在获取快速任务...");
      if(number != null){
         System.out.println(windowName+"开始为第"+number+"号快速客户服务");
         long beginTime = System.currentTimeMillis();
         try {
            Thread.sleep(Constants.MIN_SERVICE_TIME);
         }catch(InterruptedException e) {
            e.printStackTrace();
         }
         long costTime = System.currentTimeMillis() - beginTime;
         System.out.println(windowName+"完成为第"+number+"号快速客户服务,总共耗时"+(costTime/1000)+"秒");
      }
      else{
         System.out.println(windowName+"没有取到快速任务!");
         commonService();  //当没有获取到快速客户服务时,就获取普通客户服务。
      }
   }
  
   //VIP客户窗口服务。
   private void vipService() {
      String windowName = "第"+windowId+"号"+type+"窗口";
      Integer number = NumberMachine.getInstance().getVipManager().fetchServiceNumber();
      System.out.println(windowName+"正在获取VIP任务...");
      if(number != null){
         System.out.println(windowName+"开始为第"+number+"号VIP客户服务");
         long beginTime = System.currentTimeMillis();
         int maxRand = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
         long serverTime = newRandom().nextInt(maxRand)+1+Constants.MIN_SERVICE_TIME;
         try {
            Thread.sleep(serverTime);
         }catch(InterruptedException e) {
            e.printStackTrace();
         }
         long costTime = System.currentTimeMillis() - beginTime;
         System.out.println(windowName+"完成为第"+number+"号VIP客户服务,总共耗时"+(costTime/1000)+"秒");
      }
      else{
         System.out.println(windowName+"没有取到VIP任务!");
         commonService();  //当没有获取到VIP客户服务时,就获取普通客户服务。
      }
   }
}


CustomerType.java

package com.isoftstone.interview.bank;
 
//定义枚举类来限定三种类型的客户。
public enum CustomerType {
   COMMON,EXPRESS,VIP;
  
   public String toString(){
      switch (this) {
         case COMMON:
            return "普通";
      }
      switch (this) {
         case EXPRESS:
            return "快速";
      }
      switch (this) {
         case VIP:
            return "VIP";
      }
      return null;
   }
}

Constants.java

package com.isoftstone.interview.bank;
 
public class Constants {
   public static int MAX_SERVICE_TIME= 10000;   //最长服务时间,默认为10秒。
   public static int MIN_SERVICE_TIME= 1000;   //最短服务时间,默认为1秒。
   public static int COMMON_CUSTOMER_INTERVAL_TIME= 1;   //普通客户服务间隔时间,默认为1秒。
}


MainClass.java

package com.isoftstone.interview.bank;
 
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
 
public class MainClass {
 
   public static void main(String[] args) {
      //使用循环产生4个普通窗口。
      for(int x=1; x<5; x++){
         ServiceWindow commonWindow = new ServiceWindow();
         commonWindow.setWindowId(x);
         commonWindow.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 number = NumberMachine.getInstance().getCommonManager().generateNewManager();
            System.out.println("第"+number+"号普通客户正在等待服务!");
         }
      },0, Constants.COMMON_CUSTOMER_INTERVAL_TIME, 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 * 2, TimeUnit.SECONDS);
     
      //创建定时器,VIP客户拿号。
      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号普通窗口没有取到普通任务,正在空闲1秒钟 !

第2号普通窗口正在获取普通任务...

第2号普通窗口没有取到普通任务,正在空闲1秒钟 !

第3号普通窗口正在获取普通任务...

第3号普通窗口没有取到普通任务,正在空闲1秒钟 !

第1号快速窗口正在获取快速任务...

第1号快速窗口没有取到快速任务 !

第1号快速窗口正在获取普通任务...

第1号快速窗口没有取到普通任务,正在空闲1秒钟 !

第1号VIP窗口正在获取VIP任务...

第1号VIP窗口没有取到VIP任务 !

第1号VIP窗口正在获取普通任务...

第1号VIP窗口没有取到普通任务,正在空闲1秒钟 !

第4号普通窗口正在获取普通任务...

第4号普通窗口没有取到普通任务,正在空闲1秒钟 !

第1号普通客户正在等待服务!

第1号快速客户正在等待服务!

第1号VIP客户正在等待服务!

第2号普通窗口正在获取普通任务...

第2号普通窗口开始为第1号普通客户服务

第1号普通窗口正在获取普通任务...

第1号普通窗口没有取到普通任务,正在空闲1秒钟 !

第1号快速窗口正在获取快速任务...

第3号普通窗口正在获取普通任务...

第1号快速窗口开始为第1号快速客户服务

第3号普通窗口没有取到普通任务,正在空闲1秒钟 !

第4号普通窗口正在获取普通任务...

第1号VIP窗口正在获取VIP任务...

第4号普通窗口没有取到普通任务,正在空闲1秒钟 !

第1号VIP窗口开始为第1号VIP客户服务

第2号普通客户正在等待服务!

第1号普通窗口正在获取普通任务...

第1号普通窗口开始为第2号普通客户服务

第3号普通窗口正在获取普通任务...

第3号普通窗口没有取到普通任务,正在空闲1秒钟 !

第1号快速窗口完成为第1号快速客户服务,总共耗时1秒

第1号快速窗口正在获取快速任务...

第1号快速窗口没有取到快速任务 !

第1号快速窗口正在获取普通任务...

第1号快速窗口没有取到普通任务,正在空闲1秒钟 !

第4号普通窗口正在获取普通任务...

第4号普通窗口没有取到普通任务,正在空闲1秒钟 !

第3号普通客户正在等待服务!

第2号快速客户正在等待服务!

第1号快速窗口正在获取快速任务...

第3号普通窗口正在获取普通任务...

第1号快速窗口开始为第2号快速客户服务

第3号普通窗口开始为第3号普通客户服务

第4号普通窗口正在获取普通任务...

第4号普通窗口没有取到普通任务,正在空闲1秒钟 !

第4号普通客户正在等待服务!

第1号快速窗口完成为第2号快速客户服务,总共耗时1秒

第1号快速窗口正在获取快速任务...

第1号快速窗口没有取到快速任务 !

第1号快速窗口正在获取普通任务...

第1号快速窗口开始为第4号普通客户服务

第4号普通窗口正在获取普通任务...

第4号普通窗口没有取到普通任务,正在空闲1秒钟 !

第5号普通客户正在等待服务!

第3号快速客户正在等待服务!

第4号普通窗口正在获取普通任务...

第4号普通窗口开始为第5号普通客户服务





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值