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

来源:互联网 发布:t恤 知乎 编辑:程序博客网 时间:2024/05/07 10:56

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

 

银行业务调度系统要求:

1-4号窗口为普通用户窗口
5号窗口为快速用户窗口
6号窗口为VIP窗口

实际操作流程:银行-->客户-->号码机器-->(内部实现号码管理器)-->生成号码-->等待窗口叫号-->办理

面向对象的分析与设计
有三种对应类型的客户:VIP客户,普通客户,快速客户。

其实每一个客户就是由银行的一个取号机器产生号码的方式来表示的,
所以,要有一个号码管理器对象,
让这个对象不断地产生号码,
就等于随机生成了客户。

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

画图非常有助于理解和分析问题。

NumberManager(号码管理类)每一类客户的号码管理器代表每一类客户
NumberMachine(号码机器类)号码机器管理三个号码管理器
ServiceWindow(服务窗口)

例:

import java.util.ArrayList;
import java.util.List;

/**
 * 号码管理类
 */
public class NumberManager {//号码管理器
 
 private int lastNumber=1;//上一次返回的号码
 private List<Integer> queueNumber=new ArrayList<Integer>();//排队的号码
 
 public synchronized Integer generateNewNumber(){//客户生成新号码
  queueNumber.add(lastNumber);//生成的号码放入集合里
  return lastNumber++;
 }
 
 public synchronized Integer fetchNumber(){//窗口取号码
  Integer number=null;
  if(queueNumber.size()>0){
   number= queueNumber.remove(0);//先加进去的先取出来   
  }
  return number;
  //如果集合里没有值为null,则会成为空指针报错,所以,改为Integer,会自动拆箱,装箱
 }
 //由于两个不同的线程调用两个不同的方法,但方法调用了相同的数据 queueNumber ,
 //容易产生错误,所以加 synchronized 互斥
}


/**
 * 号码机器类
 */
public class NumberMachine {//号码机器
 //返回三个管理器
 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;
 }
 
 //变成单例
 private NumberMachine(){}//首先构造函数私有化
 
 public static NumberMachine getInstance(){//得到实例
  return instance;
 }
 private static NumberMachine instance=new NumberMachine();//然后实例化
 
}


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

/**
 * 服务窗口类
 */
public class ServiceWindow {//服务窗口
 private CustomerType type=CustomerType.COMMON;//固定客户用枚举
 private int windowId=1;//窗口id
 
 
 public void setType(CustomerType type) {//通过传参,来改变窗口类型
  this.type = type;
 }


 public void setWindowId(int windowId) {//通过传参,来改变窗口id
  this.windowId = windowId;
 }


 public void start(){//开始叫号,用线程池
  Executors.newSingleThreadScheduledExecutor().execute(new Runnable() {//线程池里找空闲线程
   
   @Override
   public void run() {
    while(true){//不停的取号码
     switch(type){//switch也能识别枚举类型
     case COMMON://普通用户得到普通号码     

 
      commonService();
      break;
     case EXPRESS://快速用户得到普通号码     

 
      expressService();     
      break;
     case VIP://vip用户得到普通号码 
      vipService();
      break;
     }
     
    }
    
   }
  });
 }
 //普通服务
 private void commonService(){
  String windowName="第"+windowId+"号"+type+"窗口";
  System.out.println(windowName+"正在获取任务");
  Integer number= NumberMachine.getInstance().getCommonManager().fetchNumber();   

   
  if(number!=null){
   System.out.println(windowName+"为第"+number+"个"+"普通"+"客户服务");
   long beginTime=System.currentTimeMillis();
   //最大的随机值
   int maxRand=Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME;//值9000
   long serveTime=new Random().nextInt(maxRand)+1+Constants.MIN_SERVICE_TIME;//1001

--10000毫秒
   try {
    Thread.sleep(serveTime);
   } catch (InterruptedException e) {       
    e.printStackTrace();
   }
   long costTime=System.currentTimeMillis()-beginTime;//花费时间
   System.out.println(windowName+"为第"+number+"个"+"普通"+"客户完成服务,耗

时"+costTime/1000+"秒");
   System.out.println();
  }else{
   System.out.println(windowName+"没有取到任务,先休息1秒钟");
   try {
    Thread.sleep(1000);
   } catch (InterruptedException e) {       
    e.printStackTrace();
   }
  }
 }
 //快速服务
 private void expressService(){
  String windowName="第"+windowId+"号"+type+"窗口";
  System.out.println(windowName+"正在获取任务");
  Integer number= NumberMachine.getInstance().getExpressManager().fetchNumber();   

   
  if(number!=null){
   System.out.println(windowName+"为第"+number+"个"+type+"客户服务");
   long beginTime=System.currentTimeMillis();   
   long serveTime=Constants.MIN_SERVICE_TIME;//只能是最小值
   try {
    Thread.sleep(serveTime);
   } catch (InterruptedException e) {       
    e.printStackTrace();
   }
   long costTime=System.currentTimeMillis()-beginTime;//花费时间
   System.out.println(windowName+"为第"+number+"个"+type+"客户完成服务,耗

时"+costTime/1000+"秒");
   System.out.println();
  }else{
   System.out.println(windowName+"没有取到任务");
   commonService();
  }
 }
 //vip服务
 private void vipService(){
  String windowName="第"+windowId+"号"+type+"窗口";
  System.out.println(windowName+"正在获取任务");
  Integer number= NumberMachine.getInstance().getVipManager().fetchNumber();   

   
  if(number!=null){
   System.out.println(windowName+"为第"+number+"个"+type+"客户服务");
   long beginTime=System.currentTimeMillis();
   //最大的随机值
   int maxRand=Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME;//值9000
   long serveTime=new Random().nextInt(maxRand)+1+Constants.MIN_SERVICE_TIME;//1001

--10000毫秒
   try {
    Thread.sleep(serveTime);
   } catch (InterruptedException e) {       
    e.printStackTrace();
   }
   long costTime=System.currentTimeMillis()-beginTime;//花费时间
   System.out.println(windowName+"为第"+number+"个"+type+"客户完成服务,耗

时"+costTime/1000+"秒");
   System.out.println();
  }else{
   System.out.println(windowName+"没有取到任务");   
   commonService();
  }
 }

}


/**
 * 顾客类
 */
public enum CustomerType {//三种顾客类型,普通,快速,贵宾
 COMMON,EXPRESS,VIP;
 //重写toString方法,便于理解
 public String toString(){
  switch(this){//当前对象
  case COMMON:
   return "普通";
   
  case EXPRESS:
   return "快速";
   
  case VIP:
   return name();
     
  }
  return null;
 }
}


/**
 * 常量类
 */
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;// 普通客户间隔时间

}


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++){//4个普通窗口
   ServiceWindow commonWindow= new ServiceWindow();
   commonWindow.setWindowId(i);
   commonWindow.start();
  }

  ServiceWindow expressWindow= new ServiceWindow();//快速窗口
  expressWindow.setType(CustomerType.EXPRESS);
  expressWindow.start();

  ServiceWindow vipWindow= new ServiceWindow();//vip窗口
  vipWindow.setType(CustomerType.VIP);
  vipWindow.start();
  //实现定时器功能
  Executors.newScheduledThreadPool(1).scheduleAtFixedRate(//普通顾客
    //调度线程池,池值为1,固定的频率方法
    new Runnable() {//匿名类,实际是接口对象
     
     @Override
     public void run() {
      Integer number=NumberMachine.getInstance

().getCommonManager().generateNewNumber();
      System.out.println(number+"号普通顾客等待服务!");
      
     }
    },
    0,//初始值
    Constants.COMMON_CUSTOMER_INTERVAL_TIME,//每隔多长时间
    TimeUnit.SECONDS);//以秒算
  
  Executors.newScheduledThreadPool(1).scheduleAtFixedRate(//快速顾客
    //调度线程池,池值为1,固定的频率方法
    new Runnable() {//匿名类,实际是接口对象
     
     @Override
     public void run() {      
      Integer number=NumberMachine.getInstance

().getExpressManager().generateNewNumber();
      System.out.println(number+"号快速顾客等待服务!");
      
     }
    },
    0,//初始值
    Constants.COMMON_CUSTOMER_INTERVAL_TIME * 3,//每隔多长时间
    TimeUnit.SECONDS);//以秒算
  
  Executors.newScheduledThreadPool(1).scheduleAtFixedRate(//vip顾客
    //调度线程池,池值为1,固定的频率方法
    new Runnable() {//匿名类,实际是接口对象
     
     @Override
     public void run() {
      Integer number=NumberMachine.getInstance().getVipManager

().generateNewNumber();
      System.out.println(number+"号vip顾客等待服务!");  

    
      
     }
    },
    0,//初始值
    Constants.COMMON_CUSTOMER_INTERVAL_TIME * 6,//每隔多长时间
    TimeUnit.SECONDS);//以秒算

 }

}

 

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

详细请查看:http://edu.csdn.net/heima