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

---------------------- ASP.Net+Android+IO开发S.Net培训、期待与您交流! ----------------------
银行业务调度系统
      项目需求
      银行内有六个业务窗口,1-4号为普通窗口,5号为快速窗口,6号为vip窗口

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

    异步随机生成各种类型的客户,生成各种类型用户的概率比例为:
vip客户:普通客户:快速客户=1:6:3;

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

    各类型客户在其对于窗口按顺序依次办理业务。
    当vip串口和快速窗口没有客户等待办理业务的时候,这两个窗口可以出来普通
客户的业务,而一旦有对于的客户等待办理业务的时候,则优先处理对应客户的业务

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

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

   分析与设计
    有三种对应类型的客户:VIP客户,普通客户,快速客户,异步随机生成各种类型
的客户,各种类型客户在其对应窗口按顺序依次办理业务。
    首先,经常在银行办理业务的人更有利于理解本系统,要有一个好嘛管理器对象
让这个对象不断地产生好嘛,九鼎余随机生成了客户。

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

    各类型客户在其对应窗口按顺序依次办理业务,准确地说,应该是窗口依次叫号。
    各个窗口怎么知道该叫哪一个号呢?他一定是问的相应的号码管理器,即服务窗口
每次找号码管理器获取当前要被服务的号码
    
NumberManager和NumberMachine类
    NumberManager类
    定义一个用于存储上一个客户号码的成员变量和用户所有等待服务的客户号码的队列集合

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

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

    将NumberMachine类设计成单例模式。
    ServiceWindow与CustomerType类
    CustomerType枚举类
    系统中有三种类型的客户,所有用定义一个枚举类,其中定义三个成员分别表示三种类型的客户
    重写toString方法,返回类型的中文名称,这是在后面编码时重构出来的,刚开始不用考虑
    ServiceWindow类
    定义一个start方法,内部启动一个县城,根据服务窗口的累呗分别循环调用三个不同的方法。
    定义三个方法分别对三种客户进行服务,为了观察运行效果,应详细打印出其中的细节信息。
    MainClass类和Constants类
    MainClass类
    用for循环创建出4个普通窗口,再创建出一个快速窗口和一个VIP窗口

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

    Constants类
    定义三个常量:MAX_SERVICE_TIME,MIN_SERVICE_TIME,
COMMON_CUSTOMER_INTERVAL_TIME.

      代码实现如下
package cn.itheima.bank;

public enum CustomerType {
COMMON,EXPRESS,VIP;//产生三种客户
public String toString() {//重写toString
String name = null;
switch (this) {
case COMMON:
return name="普通";
case EXPRESS:
return name="快速";
case VIP:
return name=name();
}
return name;
}
}

package cn.itheima.bank;

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

public class NumberManager {
private int lastNumber=0;//产生的号码
private List<Integer> queueNumber=new ArrayList<Integer>();//定义数组来存储号码
//因为这个数据是多个线程共享的所以要加锁
public synchronized Integer generateNewManager() {
queueNumber.add(++lastNumber);//每次自加一之后保存到数组里面去
return lastNumber;
}
//因为这个数据是多个线程共享的所以要加锁
public synchronized Integer fetchServiceNumber() {
Integer number = null;//定义一个收集号码
if(queueNumber.size()>0) {
return number = queueNumber.remove(0);//删除一个号码,然后把删除的号码保存到number里面
}
return null;
}

}

package cn.itheima.bank;

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();
}


package cn.itheima.bank;

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


package cn.itheima.bank;

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

public class ServiceWindow {
private CustomerType type = CustomerType.COMMON;//调用枚举,初始化为“普通”
private int windowId=1;//定义窗口的ID
//Vip和快速窗口的赋值
public void setType(CustomerType type) {
this.type = type;
}
//普通窗口的窗口号
public void setWindowId(int windowId) {
this.windowId = windowId;
}
//运行方法
public void start() {
Executors.newSingleThreadExecutor().execute(new Runnable() {//利用一个线程池开启一个线程
public void run() {//重写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 +"正在获取普通服务");
//如果获得的客户的号码不为null
if(number!=null) {
System.out.println(windowName+"开始为第"+number+"号普通客户服务");
//计算客户办理业务的时间,本系统设置为随机在1秒到10秒钟
int maxSereTime = Constants.MAX_SERVOCE_TIME-Constants.MIN_SERVICE_TIME;
int serveTime = new Random().nextInt(maxSereTime)+1+Constants.MIN_SERVICE_TIME;
try {
//客户办理业务的时间,停止该窗口其他业务
Thread.sleep(serveTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(windowName+"完成为第"+number +"号普通客户完成服务,耗时"+serveTime/1000+"秒");
}else {//如果客户为null
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 +"开始获取快速服务");
//如果快速客户不为null
if(number!=null) {
System.out.println(windowName+"开始为第"+number+"号快速客户服务" );
//因为是快速客户,所有时间是最短的,此处系统设置为1秒
int serviceTime = Constants.COMMON_SUSTOMER_INTERVAL_TIME;
try {
//办理快速客户业务的时间
Thread.sleep(Constants.MIN_SERVICE_TIME);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(windowName+"完成为第"+number+"号快速客户服务,耗时"+serviceTime/1000+"秒");
}else {//如果快速客户为Null
System.out.println(windowName+"没有取到服务任务");
//帮助处理普通客户的业务
CommonService();
}
}
//vip客户的处理方法
private void vipService() {
String windowName = "第"+windowId+"号"+type+"窗口";
//获取vip客户的号码值
Integer number = NumberMachine.getInstance().getVipManager().fetchServiceNumber();
System.out.println(windowName +"开始获取vip服务");
//如果vip客户不为null
if(number!=null) {
System.out.println(windowName+"开始为第"+number+"号vip客户服务" );
//计算vip客户办理业务的时间,本系统设置的时间在1秒-10秒之间的随机数
int maxRandom = Constants.MAX_SERVOCE_TIME - Constants.MIN_SERVICE_TIME;
int serviceTime = new Random().nextInt(maxRandom)+1 + Constants.MIN_SERVICE_TIME;
try {
//为vip客户服务的时间。
Thread.sleep(serviceTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(windowName+"完成为第"+number+"号vip客户完成服务,耗时"+serviceTime/1000+"秒");
}else {//如果vip客户为null
System.out.println(windowName+"没有取到服务任务!");
//就去办理普通客户的业务
CommonService();
}
}
}


package cn.itheima.bank;

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

public class MainClass {
public static void main(String[] args) {
//创建4个普通业务窗口
for(int i =1;i<5;i++) {
ServiceWindow commonWindow = new ServiceWindow();
commonWindow.setWindowId(i);
commonWindow.start();
}
//创建快速客户业务窗口
ServiceWindow expresswindow = new ServiceWindow();
expresswindow.setType(CustomerType.EXPRESS);
expresswindow.start();
//创建vip客户业务窗口
ServiceWindow vipWindow = new ServiceWindow();
vipWindow.setType(CustomerType.VIP);
vipWindow.start();
//创建一个普通客户拿号的线程池,开启一个线程,
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable() {

@Override
public void run() {
Integer number = NumberMachine.getInstance().getCommonManager().generateNewManager();
System.out.println(number+"号普通客户等待服务!");
}
},
0,
Constants.COMMON_SUSTOMER_INTERVAL_TIME,
TimeUnit.SECONDS
);
//创建一个快速客户拿号的线程池,开启一个线程,
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable() {

@Override
public void run() {
Integer number = NumberMachine.getInstance().getExpressManager().generateNewManager();
System.out.println(number+"号快速客户等待服务!");
}
},
0,
Constants.COMMON_SUSTOMER_INTERVAL_TIME*2,
TimeUnit.SECONDS
);

//创建一个vip客户拿号的线程池,开启一个线程,
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable() {

@Override
public void run() {
Integer number = NumberMachine.getInstance().getVipManager().generateNewManager();
System.out.println(number+"号VIP客户等待服务!");
}
},
0,
Constants.COMMON_SUSTOMER_INTERVAL_TIME*6,
TimeUnit.SECONDS
);
}
}
---------------------- ASP.Net+Android+IO开发S.Net培训、期待与您交流! ----------------------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值