黑马程序员——银行业务调度系统
来源:互联网 发布:变形金刚5豆瓣知乎 编辑:程序博客网 时间:2024/06/09 18:22
银行业务调度系统的业务需求为:
模拟实现银行业务调度系统逻辑,具体需求如下:
Ø 银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。
Ø 有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。
Ø 异步随机生成各种类型的客户,生成各类型用户的概率比例为:
VIP客户 :普通客户 :快速客户 = 1 :6 :3。
Ø 客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需的时间,快速客户办理业务所需时间为最小值(提示:办理业务的过程可通过线程Sleep的方式模拟)。
Ø 各类型客户在其对应窗口按顺序依次办理业务。
Ø 当VIP(6号)窗口和快速业务(5号)窗口没有客户等待办理业务的时候,这两个窗口可以处理普通客户的业务,而一旦有对应的客户等待办理业务的时候,则优先处理对应客户的业务。
Ø 随机生成客户时间间隔以及业务办理时间最大值和最小值自定,可以设置。
Ø 不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。
一、 分析
这个系统是要实现客户到银行办理业务的过程,那么我们想一下这个过程:
一个客户要到银行办理业务,就要先到取号机上取对应的号码(普通、快速、vip),然后到相应的窗口办理业务。
这段话中显现出来的对象有:客户(以String代替)、取号机、窗口。
这段话中隐含的对象有:取号机控制器
1、取号机:
一个客户到银行办理业务,它取号越早,则越先办理它的业务,那么我们可知取号机内部封装了一个队列集合,此处我们使用的为ArrayList集合。一个客户取到号码就相当于此客户添加入集合,此客户办理完业务就相当于此客户从集合中删除,那么我们可知取号机中有两个方法:一个是将元素添加入集合末尾,一个是将集合中首元素从集合中删除。
2、取号机控制器
银行中有三种取号机:普通取号机、快速取号机、vip取号机,客户从相应的取号机中取得号码,即将此客户存入相应的集合中,并且相应类型的取号机的集合只允许存在一个,所以这三种取号机都只允许存在一个对象,那么我们就是通过取号机控制器实现三种取号机的单例,并且因此取号机控制器也为单例模式来实现的。也就是说:取号机控制器中创建了三个取号机对象。我们可以通过相应方法,获取相应的取号机对象。
取号机控制器中有三个方法返回相应的取号机,多次调用的同一个方法,返回的为同一个取号机。
3、窗口:
银行中有三种窗口,所以窗口类中有一个变量,用来标记当前窗口的类型。窗口对外提供服务是独立存在的,所以单独创建一个线程用来启动窗口服务。而窗口的类型不同它启动的服务不同,所以我们要识别窗口的类型,启动相应的服务。而普通、快速、vip这三种不同的服务,又被定义为三个不同的方法。
这样银行调度系统中所要实现的重要的三个主类已经分析完了,接下来我们就要实现它。
二、 实现过程
1、实现取号器
我们已知,取号器中封装了一个ArrayList集合用来将客户取出的号码存入此集合中,那么我们如何得知客户取出的号码为多少,那我们就需要在取号器中定义一个int型变量,记录最后取出号码。取号器的代码为:
public class NumberManager {
//用来标记最后一个号码
private int lastNumber = 0;
private List queueNumbers = new ArrayList();
//当客户取出一个号码,就将此号码存入集合中去,并返回上一个号码,为了防止多线程调用出现错误,此方法用synchronized关键字修饰
public synchronized Integer generateNewNumber(){
queueNumbers.add(++lastNumber);
return lastNumber;
}
//如果集合中有元素,就删除集合中角标为0的元素,并返回此元素,如果集合中没有元素,返回null,此方法用synchronized关键字修饰
public synchronized Integer fetchNumber(){
if(queueNumbers.size()>0){
return (Integer)queueNumbers.remove(0);
}else{
return null;
}
}
}
2、实现取号控制器
此类用单例模式实现,有三个相应方法将vip、快速、普通三种不同的窗口对象返回,多次调用同一方法,返回的为同一对象。此类的实现方式为:
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();
//创建私有的vip取号器对象
private NumberManager vipManager = new NumberManager();
//将相应的取号器对象通过相应的方法返回出去
public NumberManager getCommonManager() {
return commonManager;
}
public NumberManager getExpressManager() {
return expressManager;
}
public NumberManager getVipManager() {
return vipManager;
}
}
3、窗口
窗口中应该有一个标记,用来标记当前窗口的类型此处我们将此标记定义为枚举:
public enum CustomerType {
COMMON,EXPRESS,VIP;
}
客户办理业务的时间有最大值、最小值,不同类型客户来银行的比例也不同,我们也将此定义为一个类,用来记录常量数据。
public class Constants {
public static int MAX_SERVICE_TIME = 10000;
public static int MIN_SERVICE_TIME = 1000;
public static int COMMON_CUSTOMER_INTERVAL_TIME = 1;
}
至此窗口类的内部已经明晰为:
public class ServiceWindow {
//用来标记窗口类型
private CustomerType type = CustomerType.COMMON;
//用来获取窗口类型
public CustomerType getType() {
return type;
}
//用来改变窗口类型
public void setType(CustomerType type) {
this.type = type;
}
//新建一个线程用来启动该窗口,即该窗口开始服务了
public void start(){
Executors.newSingleThreadExecutor().execute(
new Runnable(){
public void run(){
//true表示该窗口一旦启动,就一直处于服务状态
while(true){
//针对相应的窗口类型,启动相应的服务
switch(type){
case COMMON:
commonService();
break;
case EXPRESS:
expressService();
break;
case VIP:
vipService();
break;
}
}
}
}
);
}
//普通窗口服务过程实现
private void commonService(){
//获取取号机控制器对象
NumberMachine qhjkzq =NumberMachine.getInstance();
//通过取号机控制器对象获取相应的取号机对象
NumberManager qhj=qhjkzq.getExpressManager();
//获取取号机中集合下标为0的客户号码。
Integer serviceNumber =qhj.fetchNumber();
//如果集合非空,即有客户在等待服务,则执行
if(serviceNumber != null ){
//获取服务时间
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("完成客户服务,总共耗时" + serviceTime/1000 + "秒");
}else{
System.out.println(windowName + "没有取到普通任务,空闲一秒");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//快速窗口服务过程实现(过程类似)
private void expressService(){
**************
If(serviceNumber != null)
{
****************
}
else
{
System.out.println(windowName + "没有取到快速任务!");
//快速窗体服务普通客户
commonService();
}
}
//vip窗口服务过程(过程类似)
private void vipService(){
**************
If(serviceNumber != null)
{
****************
}
else
{
System.out.println(windowName + "没有取到vip任务!");
//vip窗体服务普通客户
commonService();
}
}
这样银行调度系统的三个主类已经设计好了,我们只要创建一个类在Main方法中存入客户并调用它们就好了。
4、MainClass
在main方法中创建相应的服务窗口并启动,另在main方法中启动三个线程,用来向三个相应的取号器中存入客户。
public class MainClass {
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();
System.out.println("第" + serviceNumber + "号普通客户正在等待服务!");
}
},
0,
Constants.COMMON_CUSTOMER_INTERVAL_TIME,
TimeUnit.SECONDS);
//每隔2秒,来一个快速客户拿号
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);
//每隔6秒,来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,
TimeUnit.SECONDS);
}
}
总算写完了,蚊子好多咬死我了。
- 黑马程序员——银行业务调度系统
- 黑马程序员——银行业务调度系统
- 黑马程序员——银行业务调度系统
- 黑马程序员——银行业务调度系统
- 黑马程序员——银行业务调度系统
- 黑马程序员——银行业务调度系统
- 黑马程序员——银行业务调度系统
- 黑马程序员——银行业务调度系统
- 黑马程序员——银行业务调度系统
- 黑马程序员——银行业务调度系统
- 黑马程序员——银行业务调度系统
- 黑马程序员——银行业务调度系统
- 黑马程序员——银行业务调度系统
- 黑马程序员——银行业务调度系统
- 黑马程序员——银行业务调度系统
- 黑马程序员——银行业务调度系统
- 黑马程序员——银行业务调度系统
- 黑马程序员——银行业务调度系统
- 黑马程序员 LINQ(1) 介绍LINQ、语法 总结
- C++学习笔记(三)
- cocos2d-x 植物大战僵尸(7) 触摸植物卡产生植物枪
- Single Number II
- 遍历聚合对象中的元素——迭代器模式(一)
- 黑马程序员——银行业务调度系统
- C语言字符数组的应用
- OpenGL win8x64企业版+vs2012配置。
- Android HOME键那些事
- 遍历聚合对象中的元素——迭代器模式(二)
- setPositiveButton和setNegativeButton
- iOS WebView的用法
- 遍历聚合对象中的元素——迭代器模式(三)
- 关于Authority-check