您的位置:首页 > 其它

银行业务调度系统

2014-03-12 00:50 295 查看

今天在网上看到一道关于银行业务调度系统的题目,感觉有点意思,就动手写了写代码,记录一下。

题目:

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

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

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

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

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

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

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

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

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

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

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

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

对题目进行分析,

有三种类型的客户,他们的身份(职责)并不相同,但是他们的方法确实相同的,所以定义了三个方法相同的接口IVIPCustom,IExpressCustom和ICommonCustom。

package com.garychow.interfaces;

public interface IVIPCustom {
public int getNeedsTime();
public String getName();
}
package com.garychow.interfaces;

public interface IExpressCustom {
public int getNeedsTime();
public String getName();
}
package com.garychow.interfaces;

public interface ICommonCustom {
public int getNeedsTime();
public String getName();
}


三类客户分别对应了三种职责的窗口,普通窗口,快速窗口和VIP窗口。所以,也需要三个接口,ICommonServiceWindow,IExpressServiceWindow和IVIPServiceWindow。

package com.garychow.interfaces;

public interface ICommonServiceWindow {
public boolean service(ICommonCustom custom);
}
package com.garychow.interfaces;

public interface IExpressServiceWindow {
public boolean service(IExpressCustom custom);
}
package com.garychow.interfaces;

public interface IVIPServiceWindow {
public boolean service(IVIPCustom custom);
}


最后,有一个调度业务窗口和用户的系统,同时根据题意,是通过号码来进行管理调度的,我把他们的职责归纳到一起,所以有一个INumberMachine接口。

package com.garychow.interfaces;

//	INumberMachine是整个系统的调度类,负责管理维护和处理服务顺序等
public interface INumberMachine {

//	产生一个普通客户
public void generateCommonCustom();
//	产生一个VIP客户
public void generateVIPCustom();
//	产生一个快速客户
public void generateExpressCustom();

//	为下一个普通客户服务
public void serviceNextCommonCustom();
//	为下一个VIP客户服务
public void serviceNextVIPCustom();
//	为下一个快速客户服务
public void serviceNextExpressCustom();
}


接口声明到此就结束了。

现在需要来考虑具体实现了:

首先需要定义常量:

package com.garychow.classes;

public class Constants {
public static final int GENERATE_INTERVAL_TIME 	=	1;
public static final int CUSTOM_NEEDS_TIME_MAX	=	6;
public static final int CUSTOM_NEEDS_TIME_MIN	=	2;
}


然后需要实现ICommonCustom,IExpressCustom和IVIPCustom接口。

package com.garychow.classes;

import com.garychow.interfaces.ICommonCustom;

public class CommonCustom implements ICommonCustom {

@Override
public int getNeedsTime() {
return time;
}

@Override
public String getName() {
return name;
}

private int time = (int)((Math.random() * (Constants.CUSTOM_NEEDS_TIME_MAX - Constants.CUSTOM_NEEDS_TIME_MIN)
+ Constants.CUSTOM_NEEDS_TIME_MIN) * 1000);
private String name = ++number + "号普通客户";
private static int number = 0;

}
package com.garychow.classes;

import com.garychow.interfaces.IVIPCustom;

public class VIPCustom implements IVIPCustom {

@Override
public int getNeedsTime() {
return time;
}

@Override
public String getName() {
return name;
}

private int time = (int)((Math.random() * (Constants.CUSTOM_NEEDS_TIME_MAX - Constants.CUSTOM_NEEDS_TIME_MIN)
+ Constants.CUSTOM_NEEDS_TIME_MIN) * 1000);
private String name = ++number + "号VIP客户";
private static int number = 0;

}
package com.garychow.classes;

import com.garychow.interfaces.IExpressCustom;

public class ExpressCustom implements IExpressCustom {

@Override
public int getNeedsTime() {
return time;
}

@Override
public String getName() {
return name;
}

private int time = (Constants.CUSTOM_NEEDS_TIME_MIN * 1000);
private String name = ++number + "号快速顾客";

private static int number = 0;
}


普通客户可以由任意一个窗口服务,而VIP客户和快速客户只能通过相应的窗口获得服务,因为,我认为这个可以设计为一个责任链,把普通客户交给链头,直到有窗口能服务客户或者都暂时不能服务为止。因为设计一个抽象类AResponsibilityChainCommonWindow实现ICommonServiceWindow接口。

package com.garychow.classes;

import com.garychow.interfaces.ICommonCustom;
import com.garychow.interfaces.ICommonServiceWindow;

public abstract class AResponsibilityChainCommonWindow implements ICommonServiceWindow {
private ICommonServiceWindow nextCommonServiceWindow;
public ICommonServiceWindow getNextCommonServiceWindow() {
return nextCommonServiceWindow;
}
public void setNextCommonServiceWindow(ICommonServiceWindow nextCommonServiceWindow) {
this.nextCommonServiceWindow = nextCommonServiceWindow;
}

@Override
public boolean service(ICommonCustom custom) {
if (null != nextCommonServiceWindow) {
return nextCommonServiceWindow.service(custom);
}
return false;
}
}


责任链已经搞定了,现在发现调度系统需要了解各个窗口的状态,好分配客户到窗口去。这是一个典型的观察者,而窗口们就是被观察者。因为实现一个观察者类WindowObserver,由它去通知INumberMachine。

package com.garychow.classes;

import com.garychow.interfaces.INumberMachine;

public class WindowObserver {

public static WindowObserver getInstance() {
return WindowObserverHolder.wo;
}

private static class WindowObserverHolder {
public static final WindowObserver wo = new WindowObserver();
}

private WindowObserver() {

}

public void commonWindowServiceFinish() {
nm.serviceNextCommonCustom();
}
public void vipWindowServiceFinish() {
nm.serviceNextVIPCustom();
}
public void expressWindowServiceFinish() {
nm.serviceNextExpressCustom();
}

private INumberMachine nm = NumberMachine.getInstance();
}


到这里整体的思路全部都清晰了,下面只要把方法都实现出来就好了。

类CommonWindow继承AResponsibilityChainCommonWindow,实现服务客户的方法。

package com.garychow.classes;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import com.garychow.interfaces.ICommonCustom;

public class CommonWindow extends AResponsibilityChainCommonWindow {

public CommonWindow(String name) {
this.name = name;
}

@Override
public boolean service(ICommonCustom custom) {

if (isServicing) {
return super.service(custom);
}

isServicing = true;
final ICommonCustom fCustom = custom;
executor.execute(new Runnable() {
@Override
public void run() {
try {
long beginTime = System.nanoTime();
System.out.println(name + "开始为普通顾客:" + fCustom.getName() + "服务");
Thread.sleep(fCustom.getNeedsTime());
long endTime = System.nanoTime();
System.out.println(name + "服务顾客" + fCustom.getName() + "完毕,服务时间为:" + (endTime - beginTime));
} catch (InterruptedException e) {

} finally {
isServicing = false;
WindowObserver.getInstance().commonWindowServiceFinish();
}
}
});

return true;
}

private Executor executor = Executors.newSingleThreadExecutor();
private boolean isServicing;
private String name;
}


VIPServiceWindow也继承AResponsibilityChainCommonWindow类,因为它也是处理普通客户的链上的一环,同时要实现IVIPServiceWindow接口,处理VIP客户服务。

package com.garychow.classes;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import com.garychow.interfaces.ICommonCustom;
import com.garychow.interfaces.IVIPCustom;
import com.garychow.interfaces.IVIPServiceWindow;

public class VIPServiceWindow extends AResponsibilityChainCommonWindow implements IVIPServiceWindow {

public VIPServiceWindow(String name) {
this.name = name;
}

@Override
public boolean service(ICommonCustom custom) {

if (isServicing) {
return super.service(custom);
}

isServicing = true;
final ICommonCustom fCustom = custom;
executor.execute(new Runnable() {
@Override
public void run() {
try {
long beginTime = System.nanoTime();
System.out.println(name + "开始为普通顾客:" + fCustom.getName() + "服务");
Thread.sleep(fCustom.getNeedsTime());
long endTime = System.nanoTime();
System.out.println(name + "服务顾客" + fCustom.getName() + "完毕,服务时间为:" + (endTime - beginTime));
} catch (InterruptedException e) {

} finally {
isServicing = false;
WindowObserver.getInstance().commonWindowServiceFinish();
}
}
});

return true;
}

@Override
public boolean service(IVIPCustom custom) {
if (isServicing) {
return  false;
}

isServicing = true;
final IVIPCustom fCustom = custom;
executor.execute(new Runnable() {
@Override
public void run() {
try {
long beginTime = System.nanoTime();
System.out.println(name + "开始为VIP顾客:" + fCustom.getName() + "服务");
Thread.sleep(fCustom.getNeedsTime());
long endTime = System.nanoTime();
System.out.println(name + "服务顾客" + fCustom.getName() + "完毕,服务时间为:" + (endTime - beginTime));
} catch (InterruptedException e) {

} finally {
isServicing = false;
WindowObserver.getInstance().vipWindowServiceFinish();
}
}
});

return true;
}

private Executor executor = Executors.newSingleThreadExecutor();
private boolean isServicing;
private String name;

}


同样的,ExpressServiceWindow和VIPServiceWdinow类似。

package com.garychow.classes;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import com.garychow.interfaces.ICommonCustom;
import com.garychow.interfaces.IExpressCustom;
import com.garychow.interfaces.IExpressServiceWindow;

public class ExpressServiceWindow extends AResponsibilityChainCommonWindow
implements IExpressServiceWindow {

public ExpressServiceWindow(String name) {
this.name = name;
}

@Override
public boolean service(IExpressCustom custom) {
if (isServicing) {
return false;
}

isServicing = true;
final IExpressCustom fCustom = custom;
executor.execute(new Runnable() {
@Override
public void run() {
try {
long beginTime = System.nanoTime();
System.out.println(name + "开始为快速顾客:" + fCustom.getName() + "服务");
Thread.sleep(fCustom.getNeedsTime());
long endTime = System.nanoTime();
System.out.println(name + "服务顾客" + fCustom.getName() + "完毕,服务时间为:" + (endTime - beginTime));
} catch (InterruptedException e) {

} finally {
isServicing = false;
WindowObserver.getInstance().expressWindowServiceFinish();
}
}
});

return true;
}

@Override
public boolean service(ICommonCustom custom) {

if (isServicing) {
return super.service(custom);
}

isServicing = true;
final ICommonCustom fCustom = custom;
executor.execute(new Runnable() {
@Override
public void run() {
try {
long beginTime = System.nanoTime();
System.out.println(name + "开始为普通顾客:" + fCustom.getName() + "服务");
Thread.sleep(fCustom.getNeedsTime());
long endTime = System.nanoTime();
System.out.println(name + "服务顾客" + fCustom.getName() + "完毕,服务时间为:" + (endTime - beginTime));
} catch (InterruptedException e) {

} finally {
isServicing = false;
WindowObserver.getInstance().commonWindowServiceFinish();
}
}
});

return true;
}

private Executor executor = Executors.newSingleThreadExecutor();
private boolean isServicing;
private String name;

}


写到这里,只需要把调度系统给实现就好了。代码如下:

package com.garychow.classes;

import java.util.Queue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

import com.garychow.interfaces.ICommonCustom;
import com.garychow.interfaces.ICommonServiceWindow;
import com.garychow.interfaces.IExpressCustom;
import com.garychow.interfaces.IExpressServiceWindow;
import com.garychow.interfaces.INumberMachine;
import com.garychow.interfaces.IVIPCustom;
import com.garychow.interfaces.IVIPServiceWindow;

public class NumberMachine implements INumberMachine {

private static class NumberMachineHolder {
public final static NumberMachine nm = new NumberMachine();
}

private NumberMachine() {
executor = Executors.newSingleThreadExecutor();

commonCustoms = new LinkedBlockingQueue<ICommonCustom>();
vipCustoms = new LinkedBlockingQueue<IVIPCustom>();
expressCustoms = new LinkedBlockingQueue<IExpressCustom>();

AResponsibilityChainCommonWindow cw1 = new CommonWindow("一号普通窗口");
AResponsibilityChainCommonWindow cw2 = new CommonWindow("二号普通窗口");
AResponsibilityChainCommonWindow cw3 = new CommonWindow("三号普通窗口");
AResponsibilityChainCommonWindow cw4 = new CommonWindow("四号普通窗口");

VIPServiceWindow vw = new VIPServiceWindow("VIP窗口");
ExpressServiceWindow ew = new ExpressServiceWindow("快速窗口");

cw1.setNextCommonServiceWindow(cw2);
cw2.setNextCommonServiceWindow(cw3);
cw3.setNextCommonServiceWindow(cw4);
cw4.setNextCommonServiceWindow(ew);
ew.setNextCommonServiceWindow(vw);

commonServiceWindowChainHeader = cw1;
expressServiceWindow = ew;
vipServiceWindow = vw;
}

public static INumberMachine getInstance() {
return NumberMachineHolder.nm;
}

@Override
public void generateCommonCustom() {
ICommonCustom custom = new CommonCustom();
commonCustoms.offer(custom);
serviceNextCommonCustom();
}

@Override
public void generateVIPCustom() {
IVIPCustom custom = new VIPCustom();
vipCustoms.offer(custom);
serviceNextVIPCustom();
}

@Override
public void generateExpressCustom() {
IExpressCustom custom = new ExpressCustom();
expressCustoms.offer(custom);
serviceNextExpressCustom();
}

@Override
public void serviceNextCommonCustom() {
executor.execute(new Runnable() {

@Override
public void run() {
serviceNextCommonCustom(commonServiceWindowChainHeader);
}
});

}

@Override
public void serviceNextVIPCustom() {
executor.execute(new Runnable() {

@Override
public void run() {
if (!serviceNextVIPCustom(vipServiceWindow)) {
serviceNextCommonCustom(vipServiceWindow);
}
}
});
}

@Override
public void serviceNextExpressCustom() {
executor.execute(new Runnable() {

@Override
public void run() {
if (!serviceNextExpressCustom(expressServiceWindow)) {
serviceNextCommonCustom(expressServiceWindow);
}
}
});
}

private boolean serviceNextCommonCustom(ICommonServiceWindow window) {
boolean isServiced = false;
if (!commonCustoms.isEmpty()) {
ICommonCustom custom = commonCustoms.element();
if (isServiced = window.service(custom)) {
commonCustoms.poll();
}
}
return isServiced;
}
private boolean serviceNextExpressCustom(IExpressServiceWindow window) {
boolean isServiced = false;
if (!expressCustoms.isEmpty()) {
IExpressCustom custom = expressCustoms.element();
if (isServiced = window.service(custom)) {
expressCustoms.poll();
}
}
return isServiced;
}
private boolean serviceNextVIPCustom(IVIPServiceWindow window) {
boolean isServiced = false;
if (!vipCustoms.isEmpty()) {
IVIPCustom custom = vipCustoms.element();
if (isServiced = window.service(custom)) {
vipCustoms.poll();
}
}
return isServiced;
}

private final Executor executor;
private final Queue<ICommonCustom> commonCustoms;
private final Queue<IVIPCustom> vipCustoms;
private final Queue<IExpressCustom> expressCustoms;

private final AResponsibilityChainCommonWindow commonServiceWindowChainHeader;
private final ExpressServiceWindow expressServiceWindow;
private final VIPServiceWindow vipServiceWindow;

}


最后,写出场景类调用就可以模拟银行调度系统了。

package com.garychow.classes;

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

import com.garychow.interfaces.INumberMachine;

public class Context {

public static void main(String[] args) {
final INumberMachine nm = NumberMachine.getInstance();

Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {

@Override
public void run() {
double random = Math.random();
if (random < 0.1) {
nm.generateVIPCustom();
} else if (random >= 0.1 && random < 0.4) {
nm.generateExpressCustom();
} else {
nm.generateCommonCustom();
}

}
}, 0, Constants.GENERATE_INTERVAL_TIME, TimeUnit.SECONDS);
}

}


到此,这个题目就算完全做完了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: