黑马程序员--银行调度系统之学习

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

银行调度系统

 

 

 

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

 

  1. 银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。
  2. 有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。
  3. 异步随机生成各种类型的客户,生成各类型用户的概率比例为:

 

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

 

  4.客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需

  的时间,快速客户办理业务所需时间为最小值(提示:办理业务的过程可通过线程Sleep的方式模拟)。

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

  6.当VIP(6号)窗口和快速业务(5号)窗口没有客户等待办理业务的时候,这两个窗口可以处理普通客户

  的业务,而一旦有对应的客户等待办理业务的时候,则优先处理对应客户的业务。

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

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

 

二: 面向对象需求分析和设计

  1,窗口对象,每种类型的窗口对应不同的客户类型,每个窗口叫号,让客户来办理业务

  2,客户类型,使用枚举类型(客户没有什么动作,有动作的是窗口业务员),所以客户不封装类

  3,随机生成客户实例,功能实现,联系实际,想到要有一个号码管理器对象,让这个对象不断地产生号码,就等于随机生成了客户。

  三个号码管理器对象由一个号码机器进行管理,这个号码机器在整个系统中始终只能有一个,所以,它要被设计成单例。

  4,定义最大最小值常量,快速窗口服务时间最短

  5,依次办理业务,可定义队列,办理一个删除一个

三:主要类分析: 

1、号码管理器对象(NumberManager)

 分析:当银行窗口叫号的时候,是从号码管理器对象获取应该叫的号码的。
所以这里应该有个获取方法,能够分别获取三种不同的客户,提供给三种不同的业务窗口
同时,需要判断,当VIP客户没有时,VIP窗口也可以获取普通客户,为普通客户服务。
当快速客户没有时,快速窗口也可以获取普通客户,为普通客户服务。

2、产生号码机器对象(NumberMachine)
观察发现 取号机产生号,产生一个号就相当于产生了一个客户。所以建立取号机对象,不断产生号,就相当于不断产生客户.
因为只有一个取号机,却有3种客户,所以这个机器要产生三个号码管理器对象,而一个机器同一时间,只能产生一个号,

所以这NumberMachine对象,应该是单例模式的。并且有三个产生方法:

  • 产生VIP客户方法
  • 产生普通客户方法
  • 产生快速客户方法

 

三种不同的客户产生之后存放起来,等待号码管理器读取。

 

3、窗口对象(ServiceWindow)

 


分析:窗口对象行为:叫号,而这个叫的号是依据取号机对象生成的号来进行的。
所以,窗口对象方法 :叫号方法(传入取号机对象生成的客户号码)

 

 

 

三:代码实现

1,号码管理对象类

 

号码管理
package cn.itcast.bankqueue;

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

public class NumberManager {
    private int lastNumber = 0;
               //建立队列存储随机产生的号码
    private List queueNumbers = new ArrayList();
    
    public synchronized Integer generateNewNumber(){
        queueNumbers.add(++lastNumber);
        return lastNumber;
    }
    
    public synchronized Integer fetchNumber(){
        if(queueNumbers.size()>0){
            return (Integer)queueNumbers.remove(0);
        }else{
            return null;
        }
    }
}

2,号码产生机器类

 

产生号码机器
package cn.itcast.bankqueue;

public class NumberMachine {
    
    private NumberMachine(){}
    private static NumberMachine instance = new NumberMachine();
    public static NumberMachine getInstance(){
        return instance;
    }
    
    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,窗口对象类

 

ServiceWindow
package cn.itcast.bankqueue;

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

/**
 * 没有把VIP窗口和快速窗口做成子类,是因为实际业务中的普通窗口可以随时被设置为VIP窗口和快速窗口。
 * */
public class ServiceWindow {
    private static Logger logger = Logger.getLogger("cn.itcast.bankqueue");
    private CustomerType type = CustomerType.COMMON;
    private int number = 1;

    public CustomerType getType() {
        return type;
    }

    public void setType(CustomerType 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();
        }
    }
    //vip窗口服务
    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,客户类型,使用枚举

View Code
package cn.itcast.bankqueue;

public enum CustomerType {
    COMMON,EXPRESS,VIP;
    public String toString(){
        String name = null;
        switch(this){
        case COMMON:
            name = "普通";
            break;
        case EXPRESS:
            name = "快速";
            break;
        case VIP:
            name = name();
            break;
        }
        return name;
    }
}

5,常量值(最大最小值设置)

View Code
package cn.itcast.bankqueue;

public class Constants {
    public static int MAX_SERVICE_TIME = 10000; //10秒!
    public static int MIN_SERVICE_TIME = 1000; //1秒!
    
    /*每个普通窗口服务一个客户的平均时间为5秒,一共有4个这样的窗口,也就是说银行的所有普通窗口合起来
     * 平均1.25秒内可以服务完一个普通客户,再加上快速窗口和VIP窗口也可以服务普通客户,所以,
     * 1秒钟产生一个普通客户比较合理,*/    
    public static int COMMON_CUSTOMER_INTERVAL_TIME = 1;     
}

6,实现类

View Code
package cn.itcast.bankqueue;

import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

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,//每隔6秒产生一个 VIP客户
                TimeUnit.SECONDS);
    }

}

 

 

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

 

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

 

 

   

 

 

posted on 2012-08-11 21:21  doublewinwin  阅读(172)  评论(0编辑  收藏  举报