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

来源:互联网 发布:联合缴费软件下载 编辑:程序博客网 时间:2024/06/11 19:50

 

 http://edu.csdn.net/heima android培训http://edu.csdn.net/heima ; java培训期待与您交流!

 

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

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

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

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

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

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

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

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

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

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

面向对象分析设计:

1、每一个客户其实就是用银行取号机产生的号来表示,如果产生了一个号码,就说明有一个客户来了,所以需要定义一个取号机,然后取号机不断随机生成号,来表示客户来了。

2、有三种类型的客户,分别是普通客户,快速客户,vip客户,所以就需要产生三种不同的号码,分别是普通客户号码,快速客户号码,vip客户号码,所以就需要定义一个号码管理机器,这个号码管理机器用来管理三个生成不同种类号码的取号机,而号码管理机器只有一个,所以用单例模式来定义,内部提供返回三个不同的取号机。

3、银行中有6个窗口,4个普通窗口,1个快速窗口,一个vip窗口,这个窗口要帮客户处理业务,所以内部有一个叫号功能,这个功能内部是怎么叫的,它一定是问的相应的号码管理器,即服务窗口每次找号码管理器获取当前要被服务的号码,最先生成的号,最先被处理。

1、描述NumberManager:

思路:

1,定义一个用于存储上一个客户号码的成员变量和用于存储所有等待服务的客户号码的队列集合。
      2,定义一个产生新号码的方法和获取马上要为之服务的号码的方法,这两个方法被不同的线程操作了相同的数据,所以,要进行同步。

//号码管理器,可以产生号码和删除号码。

package cn.itcast.bank;

import java.util.ArrayList;

publicclass NumberManager {

    privateintlastNumber = 1;

    //定义一个集合用于存储号码和取出号码。

    privateList<Integer>queueNumber =new ArrayList<Integer>();

    //有一个产生号码的方法。

    publicsynchronized Integer generateNewManager(){

       queueNumber.add(lastNumber);

       returnlastNumber++;

    }

    //服务窗口服务删除号码的方法。

    //注意:返回的不能是整数,因为角标0如果不存在,返回null,是不能转成整数的,所以返回值为用Integer对象表示。

    publicsynchronized Integer fetchServiceNumber(){

       Integer number = null;

       if(queueNumber.size()>0){

           returnqueueNumber.remove(0);

       }

       return number;

    }

}

2、描述NumberMachine
思路:
      1.定义三个成员变量分别指向三个NumberManager对象,分别表示普通、快速和VIP客户的号码管理器,定义三个对应的方法来返回这三个NumberManager对象。
      2.NumberMachine类设计成单例。

package cn.itcast.bank;

//管理三种类型号码的机器,一个机器管理三种号码。

publicclass NumberMachine {

    private NumberManagercommonanager =new NumberManager();

    private NumberManagerexpressManager =new NumberManager();

    private NumberManagervipManager3 =new NumberManager();

    public NumberManager getCommonanager() {

       returncommonanager;

    }

    public NumberManager getExpressManager() {

       returnexpressManager;

    }

    publicNumberManager getVipManager() {

       returnvipManager3;

    }

    private NumberMachine(){}

    //创建一个号码管理器对象,用单例。

    privatestatic NumberMachineinstanse =new NumberMachine();

    publicstatic NumberMachine getInstanse(){

       returninstanse;

    }  

}

3ServiceWindow类编写:
思路:

 1、定义一个start方法,内部启动一个线程,根据服务窗口的类别分别循环调用三个不同的方法。
      2
、定义三个方法分别对三种客户进行服务,想要查看代码运行的效果,应该用输出语句打印出详细的运行情况。

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

package cn.itcast.bank;

import java.util.Random;

publicclass ServiceWindow {

    //定义一个变量type,用来表示窗口的类型(只有三种,所以用枚举)

    private CustomerTypetype = CustomerType.COMMON;//默认是CMMON普通的。

    //定义一个变量用于记录窗口号,有6个窗口。

    publicvoid setTyp(CustomerType type) {

       this.type = type;

    }

    publicvoid setWindowId(int windowId) {

       this.windowId = windowId;

    }

    privateintwindowId = 1;

    publicvoid start(){

       Executors.newSingleThreadExecutor().execute(new Runnable(){

           publicvoid run(){

              while(true){

                  switch(type){

                  caseCOMMON

                     commonService();

                     break;

                  caseEXPRESS:

                     expressService();

                     break;

                  caseVIP:

                     vipService();

                     break;

                  }     

              }       

           }

       });

    }

           privatevoid commonService() {

              String windowName =""+windowId+""+type+"窗口";//要覆盖toString方法。         

              Integer number = NumberMachine.getInstanse().getCommonanager().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 serveTime =new Random().nextInt(maxRand) + 1 + Constants.MIN_SERVICE_TIME;

                  try {

                     //sleep的冻结来描述为客户服务所需的最小和最大时间之间。

                     Thread.sleep(serveTime);

                  } catch (InterruptedException e) {

                     e.printStackTrace();

                  }

                  long costTime = System.currentTimeMillis() - beginTime;

                  System.out.println(windowName +"为第" + number +"" +"普通" +"客户完成服务,耗时"+(costTime/1000+""));

              }else{

                  System.out.println(windowName+"没有取到服务任务,休息1秒钟!");

                  try{

                     //没取到任务,休息1秒钟。

                     Thread.sleep(1000);

                  }catch(InterruptedException e){

                     e.printStackTrace();

                  }

              }

           }

           privatevoid expressService() {

              String windowName =""+windowId+""+type+"窗口";//要覆盖toString方法。

              Integer number = NumberMachine.getInstanse().getExpressManager().fetchServiceNumber();

              //把输出代码放在阻塞方法的后面,这样看起来更流畅。

              System.out.println(windowName+"正在获取任务");            

              //如果号码不为空,就要进行服务。

              if(number !=null){

                  //定义两个毫秒值来返回处理每次处理任务所需的时间。

                  long beginTime = System.currentTimeMillis();

                  //int maxRand = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;

                  //long serveTime = new Random().nextInt(maxRand) + 1 + Constants.MIN_SERVICE_TIME;

                  try {

                     //快速服务,只能是最小时间值。

                     Thread.sleep(Constants.MIN_SERVICE_TIME);

                  } catch (InterruptedException e) {

                     e.printStackTrace();

                  }

                  long costTime = System.currentTimeMillis() - beginTime;

                  System.out.println(windowName +"为第" + number +"" +type +"客户完成服务,耗时"+(costTime/1000+""));

              }else{

                  System.out.println(windowName+"没有取到服务任务");

                  //快速窗口没有获取到任务,就为普通用户服务。

                  commonService();

                  try{

                     //没取到任务,休息1秒钟。

                     Thread.sleep(1000);

                  }catch(InterruptedException e){

                     e.printStackTrace();

                  }

              }

           }   

           privatevoid vipService() {

              String windowName =""+windowId+""+type+"窗口";//要覆盖toString方法。

              Integer number = NumberMachine.getInstanse().getVipManager().fetchServiceNumber();

              //把输出代码放在阻塞方法的后面,这样看起来更流畅。

              System.out.println(windowName+"正在获取任务");

              //如果号码不为空,就要进行服务。

              if(number !=null){

                  //定义两个毫秒值来返回处理每次处理任务所需的时间。

                  long beginTime = System.currentTimeMillis();

                  int maxRand = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;

                  long serveTime =new Random().nextInt(maxRand) + 1 + Constants.MIN_SERVICE_TIME;

                  try {

                     //sleep的冻结来描述为客户服务所需的最小和最大时间之间。

                     Thread.sleep(serveTime);

                  } catch (InterruptedException e) {

                     e.printStackTrace();

                  }

                  long costTime = System.currentTimeMillis() - beginTime;

                  System.out.println(windowName +"为第" + number +"" +type +"客户完成服务,耗时"+(costTime/1000+""));

              }else{

                  System.out.println(windowName+"没有取到服务任务!");

                  //vip窗口没有获取到任务,就为普通用户服务。

                  commonService();

                  try{

                     //没取到任务,休息1秒钟。

                     Thread.sleep(1000);

                  }catch(InterruptedException e){

                     e.printStackTrace();

                  }

              }

           }

}

4CustomerType枚举类编写:
思路:
      1.系统中有三种类型的客户,所以用定义一个枚举类,定义的三个枚举元素分别表示三种类型的客户。
      2.重写toString方法,这样就可以返回中文。

package cn.itcast.bank;

//定义一个窗口类型的枚举

publicenum CustomerType {

    COMMON,EXPRESS,VIP;

    @Override

    //覆盖toString方法,让打印更加明了。

    public String toString(){

       switch(this){

       caseCOMMON:

           return"普通";

       caseEXPRESS:

           return"快速";

       caseVIP:

           return name();

       }

       returnnull;

    }

}

5Constants类编写:

package cn.itcast.bank;

//常量类,专门定义一个类用来放常量。

publicclassConstants {

  //最大时间为10秒。

  publicstaticintMAX_SERVICE_TIME = 10000;

  //最小时间1

  publicstaticintMIN_SERVICE_TIME = 1000;

  //普通用户间隔时间

  public staticintCOMMON_CUSTOMER_INTERVAL_TIME=1;

}

6MainClass类编写:
思路:

1,用for循环创建出4个普通窗口,再创建出1个快速窗口和一个VIP窗口。
 2 接着再创建三个定时器,分别定时去创建新的普通客户号码、新的快速客户号码、新的VIP客户号码。

package cn.itcast.bank;

import java.util.concurrent.Executors;

import java.util.concurrent.TimeUnit;

publicclass MainClass{

    publicstaticvoid main(String[] args){

       ServiceWindow commonWindow =null;

       //普通窗口有四个,所以用for循环来创建。

       for(int i=1;i<5;i++){

           commonWindow = new ServiceWindow();

           commonWindow.setWindowId(i);

           commonWindow.start();

       }

       //创建一个快速服务窗口。

       ServiceWindow expressWindow =new ServiceWindow();

       expressWindow.setTyp(CustomerType.EXPRESS);

       expressWindow.start();

       //创建一个vip窗口。

       ServiceWindow vipWindow =new ServiceWindow();

       vipWindow.setTyp(CustomerType.VIP);

       vipWindow.start();

       //定义一个线程用来处理普通客户。

       Executors.newScheduledThreadPool(1).scheduleAtFixedRate(

              new Runnable(){

                  publicvoid run(){

                     Integer number = NumberMachine.getInstanse().getCommonanager().generateNewManager();

                     System.out.println(number+"号普通客户等待服务!");

                  }

              },

              0,

              Constants.COMMON_CUSTOMER_INTERVAL_TIME,

              TimeUnit.SECONDS

              );

       //创建一个线程,用来处理快速客户。

       Executors.newScheduledThreadPool(1).scheduleAtFixedRate(

              new Runnable(){

                  publicvoid run(){

                     Integer number = NumberMachine.getInstanse().getExpressManager().generateNewManager();

                     System.out.println(number+"号快速客户客户等待服务!");

                  }

              },

              0,

              Constants.COMMON_CUSTOMER_INTERVAL_TIME*6,

              TimeUnit.SECONDS

              );

       Executors.newScheduledThreadPool(1).scheduleAtFixedRate(

              new Runnable(){

                  publicvoid run(){

                     Integer number = NumberMachine.getInstanse().getVipManager().generateNewManager();

                     System.out.println(number+"号普VIP户等待服务!");

                  }

              },

              0,

              Constants.COMMON_CUSTOMER_INTERVAL_TIME*2,

              TimeUnit.SECONDS

              );

    }

}

http://edu.csdn.net/heima android培训 http://edu.csdn.net/heima ; java培训期待与您交流!详细请查看http://edu.csdn.net/heima
原创粉丝点击