您的位置:首页 > 职场人生

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

2013-11-15 21:40 477 查看
------- android培训java培训、期待与您交流! ----------

银行业务调度系统

一、需求

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

1.2、有三种对应类型的客户:普通客户、快速客户、VIP客户。

1.3、异步随机生成各种类型的客户,生成各类型用户比例为:VIP、快速、普通:1:6:3。

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

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

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

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

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

二、需求分析

每一个客户其实就是由银行的一个取号机器产生的,所以,我们要定义一个号码管理器的对象,让这个对象不断的产生号码,就等于随机生成了客户。

因为有三类客户,每类客户的号码编排都是完全独立的,所以,本系统中要定义三个号码管理器对象,各自管理一类用户的排队号码。并且定义一个号码机器管理这三个号码管理器对象,该号码机器在整个系统中只能有一个,所以,设计成单例的模式。

客户得到服务,其实是窗口叫号,所以应该定义一个窗口服务的类,要取号,它问的是相应的号码管理器,即服务窗口每次找号码管理器获取当前要被服务的号码。

综上所述:该系统主要产生的类:号码管理器,号码机器,服务窗口。

号码管理器:NumberManager类,定义一个List集合用于存储等待服务的号码;并且提供产生号码(即用户进来取号的动作)的方法;提供取号(即服务窗口要提供服务时获取号码的动作)的方法。

package itheima.interview.bankProject;

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

//号码管理器
public class NumberManager {

//  号码从1号开始
private int lastNumber = 1;

//  该集合用于存储用户取到、但还没有进行服务的号码
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){
number = queueNumber.remove(0);
}
return number;
}
}


号码机器:NumberMachine类,定义三个号码管理器,用于管理三种不同客户的号码,即:定义三个NumberManager对象;本系统中,号码机器只能有一个,所以本类设计成单例模式。

package itheima.interview.bankProject;

//号码机器:用于管理三个号码管理器的对象
public class NumberMachine {

//  三种客户对应三种不同的号码,那么分别用三个号码管理器来管理

private NumberManager commomManager = new NumberManager();
private NumberManager expressManager = new NumberManager();
private NumberManager vipManager = new NumberManager();

//  获取普通客户的号码管理器
public NumberManager getCommomManager() {
return commomManager;
}

//  获取快速客户的号码管理器
public NumberManager getExpressManager() {
return expressManager;
}

//  获取VIP客户的号码管理器
public NumberManager getVipManager() {
return vipManager;
}

//  号码机器只有一个,单例!
//  1、私有化构造方法
private NumberMachine(){}

//  2、在本类中创建对象
private static NumberMachine instance = new NumberMachine();

//  3、向外提供获取该对象的方法
public static NumberMachine getInstance(){
return instance;
}

}


用户类型:CustomerType枚举类,系统中有普通、快速、VIP三类客户,用枚举类表示更加简单;重写toString方法,返回类型的中文名称,打印的时候更加方便我们的阅读。

服务窗口:ServiceWindow类,定义一个Start方法,内部启动一个线程,根据服务窗口的类别分别循环调用三个不同的方法为三种不同的客户进行服务;定义三个方法分别对三种客户进行服务,并且打印其中的细节信息。

package itheima.interview.bankProject;

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

//服务窗口
public class ServiceWindow {

//  默认用户的类型为:普通用户
private CustomerType type = CustomerType.COMMON;

//  默认的服务窗口为1号
private int windowId = 1;

//  设置用户的类型
public void setType(CustomerType type) {
this.type = type;
}

//  设置窗口号
public void setWindowId(int windowId) {
this.windowId = windowId;
}

//  启动窗口进行服务
public void start(){
//      窗口其实就是一条单独的线程
Executors.newSingleThreadExecutor().execute(new Runnable(){
@Override
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+"窗口";

//      窗口为普通用户服务,即:从号码机器中的 号码管理器 中的 ArrayList集合 把 号码取走
Integer number =NumberMachine.getInstance().getCommomManager().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 {
//              线程休息,模拟服务所需时间
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 {
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+"个"+type+"客户服务");
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+"个"+type+"客户完成服务,耗时"+costTime/1000);
}else{

//          如果没有快速客户,则为普通客户服务
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客户,则提供相应的服务
if(number!=null){

//          提示信息
System.out.println(windowName+"正在为第"+number+"个"+type+"客户服务");
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(serveTime);
} catch (InterruptedException e) {
e.printStackTrace();
}

//          服务耗时
long costTime = System.currentTimeMillis()- beginTime;
System.out.println(windowName+"为第"+number+"个"+type+"客户完成服务,耗时"+costTime/1000);
}else{

//          没有VIP客户,则为普通客户服务
System.out.println(windowName+"没有取到任务");
commonService();
}
}
}


主类:MainClass类,用for循环创建出4个普通的窗口,再创建出一个快速窗口和一个VIP窗口;接着创建三个定时器,分别定时去创建新的普通客户号码、快速客户号码、VIP客户号码,模拟不同的用户来取号的过程。

package itheima.interview.bankProject;

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

//      1个窗口:快速客户类型
ServiceWindow expressWindow = new ServiceWindow();

//      设置窗口类型
expressWindow.setType(CustomerType.EXPRESS);

//      设置窗口号为:5
expressWindow.setWindowId(5);

//      启动服务
expressWindow.start();

//      VIP窗口
ServiceWindow vipWindow = new ServiceWindow();

vipWindow.setType(CustomerType.VIP);

vipWindow.setWindowId(6);

vipWindow.start();

//      定时器,模拟普通客户来取票
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable(){
@Override
public void run() {

//                      产生普通客户的号码
Integer number =
NumberMachine.getInstance().getCommomManager().generateNewManager();
System.out.println(number+"号普通客户等待服务!");
}
},
0,
Constants.COMMON_CUSTOMER_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,
5*Constants.COMMON_CUSTOMER_INTERVAL_TIME,
TimeUnit.SECONDS
);

//      定时器,模拟VIP客户来取票
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable(){
@Override
public void run() {

//                      产生VIP客户的号码
Integer number =
NumberMachine.getInstance().getVipManager().generateNewManager();
System.out.println(number+"号VIP客户等待服务!");
}
},
0,
10*Constants.COMMON_CUSTOMER_INTERVAL_TIME,
TimeUnit.SECONDS
);
}
}


常量:Constants类,把常用的常量定义到一个类中,用起来更加方便,程序的阅读性更加高,所以建议以后都把常用的常量定义到一个类中。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: