---------------------- ASP.Net+Android+IOS开发</a>、.Net培训、期待与您交流! ----------------------
需求:
银行内有6个业务窗口,1- 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。
异步随机生成各种类型的客户,生成各类型用户的概率比例为:
VIP客户 :普通客户 :快速客户 = 1 :6 :3。
客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需的时间,快速客户办理业务所需时间为最小值(提示:办理业务的过程可通过线程Sleep的方式模拟)。
各类型客户在其对应窗口按顺序依次办理业务。
当VIP(6号)窗口和快速业务(5号)窗口没有客户等待办理业务的时候,这两个窗口可以处理普通客户的业务,而一旦有对应的客户等待办理业务的时候,则优先处理对应客户的业务。
随机生成客户时间间隔以及业务办理时间最大值和最小值自定,可以设置。
不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。
分析:
客户类型(ServerNumberQueue)将客户类型看成是要服务的号。固定为三种类型(VIP客户 、普通客户、快速客户),可通过枚举实现。里面用List存储当前等待服务的对象。
因为因为三个窗口可能会同时操作普通客户,所以要注意数据的正确性。用同步代码块来保证。
客户类型机器(ServerNumberMachine)用于自动三种类型的客户服务号。
服务窗口(ServiceWindow)服务客户。有三种类型窗口。
各个类的实现:
客户类型(ServerNumberQueue)
public enum ServerNumberQueue {
VIP, COMMON, FAST;
private List<String> numberQueue;//存储当前等待服务的客户号码队列
private int currentNumber; //记录当前客户号
private ServerNumberQueue() {
this.numberQueue = new LinkedList<String>();
//建立客户对象时,让客户号从一个4000-4999的随机数开始
this.currentNumber = new Random().nextInt(1000) + 4000;
}
public synchronized void setCurrentNumber(int num) {
if (this.numberQueue.size() == 0) {
this.currentNumber = num;
}
}
/*
* 当服务窗口为一个对象服务完毕,调用该方法将服务号从队列中移除
* 可能多个服务窗口会同时服务,要加同步代码块
*/
public synchronized String fetchNumber() {
if (this.numberQueue.size() > 0) {
return this.numberQueue.remove(0);
}
return null;
}
/*
* 当客户管理器产生了一个客户时,将其添加到队列中
*/
public synchronized String generateNumber() {
this.numberQueue.add(this.name() + " customer " + currentNumber++);
//System.err.println(this.numberQueue);
return this.numberQueue.get((this.numberQueue.size() - 1));
}
public synchronized int getQueueCount() {
return this.numberQueue.size();
}
}
客户类型机器(ServerNumberMachine)
public class ServerNumberMachine {
//程序运行时,只有一个客户型管理的机器,单例。
private static ServerNumberMachine instance;
/*
* 单例实现:构造方法私有,通过一个静态方法返回对象。
*/
private ServerNumberMachine(){}
public static ServerNumberMachine getInstance(){
if(instance == null){
synchronized(ServerNumberMachine.class){
if(instance == null){
instance = new ServerNumberMachine();
}
}
}
return instance;
}
/*
* 当服务窗口为客户服务时,客户管理机器要把该客户从等待服务的客户队列中移除。
*/
public String fetchCustomer(String name){
return ServerNumberQueue.valueOf(name).fetchNumber();
}
/*
* 添加客户到队列中
*/
public void generateCustomer(String name){
String mes;
mes = ServerNumberQueue.valueOf(name).generateNumber();
System.err.println("'" + mes + "'来了.");
}
}
服务窗口(ServiceWindow)
public class ServiceWindow {
private String windowName;//服务窗口名
private String windowType;//服务窗口类型
private int windowNumber;//窗口号
private ServerNumberMachine snm;
private ExecutorService pool;
public ServiceWindow(int number) {
this(ConstantsUnit.COMMON_CUSTOMER, number);
}
public ServiceWindow(String type, int number) {
this.windowType = type;
this.windowName = type;
this.windowNumber = number;
this.snm = ServerNumberMachine.getInstance();
this.pool = ThreadPool.getInstance().getExecutorService();
}
public void setWindowName(String windowName) {
this.windowName = windowName;
}
public void setWindowNumber(int windowNumber) {
this.windowNumber = windowNumber;
}
public int getWindowNumber() {
return this.windowNumber;
}
private boolean service() {
return service(windowType);
}
/*
* 查找客户并为客户服务功能
*/
private boolean service(String type) {
/*try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}*/
Random time = new Random();
//当前服务窗口sleep时间,以模拟为客户服务耗时。当为快速客户服务时,时间为1;否则随机产生一个时间
int servicetime = type.equals(ConstantsUnit.FAST_CUSTOMER) ?
ConstantsUnit.MIN_SERVICE_TIME
: time.nextInt(ConstantsUnit.MAX_SERVICE_TIME
- ConstantsUnit.MIN_SERVICE_TIME)
+ ConstantsUnit.MIN_SERVICE_TIME + 1;
String servicemess;
servicemess = snm.fetchCustomer(type);
if (servicemess != null) {
try {
/* System.out.println(windowName + windowNumber + "正在为'"
+ servicemess + "'服务");*/
long stime = System.currentTimeMillis();
Thread.sleep(servicetime);
long etime = System.currentTimeMillis();
System.out.println(windowName + windowNumber + "为'"
+ servicemess + "'服务完毕,耗时:" + (etime - stime) / 1000
+ "秒.");
return true;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/* if(type.equals(ConstantsUnit.COMMON_CUSTOMER)){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}*/
return false;
}
/*
* 调用此方法让窗口开始服务
* VIP,快速窗口没有相应的客户时,要服务普通客户
*/
public void startService() {
pool.execute(new Runnable() {
@Override
public void run() {
while (true) {
switch (windowType) {
/*
* VIP窗口成功为VIP客户服务则要继续判断是否有VIP客户等待服务,否则判断是否有等待服务的
* 普通客户,有则要为普通客户服务
*/
case "VIP":
if(service())//将查找客户并服务单独封装成一个方法,调用service方法
break;
service(ConstantsUnit.COMMON_CUSTOMER);
break;
/*
* 快速窗口成功为快速客户服务则要继续判断是否有VIP客户等待服务,否则判断是否有等待服务的
* 普通客户,有则要为普通客户服务
*/
case "FAST":
if(service())
break;
service(ConstantsUnit.COMMON_CUSTOMER);
break;
case "COMMON":
service();
}
}
}
});
}
}
用到的一些常(ConstantsUnit)
public class ConstantsUnit {
public static int MAX_SERVICE_TIME = 10000;//最大服务时间,毫秒
public static int MIN_SERVICE_TIME = 1000;//最小服务时间
public static String VIP_CUSTOMER = "VIP";
public static String COMMON_CUSTOMER = "COMMON";
public static String FAST_CUSTOMER = "FAST";
public static int GENERATE_CUSTOMER = 1;//产生普通客户的时间间隔
}
测试功能否完成(Test)
public class Test {
public static void main(String[] args){
final ServerNumberMachine snm = ServerNumberMachine.getInstance();
ThreadPool pool = ThreadPool.getInstance();
for(int i=1; i<=4; i++){
// System.out.println("创建普通服务窗口...");
new ServiceWindow(i).startService();
}
// System.out.println("创建快速服务窗口...");
new ServiceWindow(ConstantsUnit.FAST_CUSTOMER, 5).startService();
// System.out.println("创建VIP服务窗口...");
new ServiceWindow(ConstantsUnit.VIP_CUSTOMER, 6).startService();
//产生普通客户
pool.getScheduledExecutorService().scheduleAtFixedRate(
new Runnable(){
@Override
public void run() {
snm.generateCustomer(ConstantsUnit.COMMON_CUSTOMER);
}
},
0,
ConstantsUnit.GENERATE_CUSTOMER,
TimeUnit.SECONDS);
//产生VIP客户
pool.getScheduledExecutorService().scheduleAtFixedRate(
new Runnable(){
@Override
public void run() {
snm.generateCustomer(ConstantsUnit.VIP_CUSTOMER);
}
},
0,
ConstantsUnit.GENERATE_CUSTOMER*6,
TimeUnit.SECONDS);
//产生快速客户
pool.getScheduledExecutorService().scheduleAtFixedRate(
new Runnable(){
@Override
public void run() {
snm.generateCustomer(ConstantsUnit.FAST_CUSTOMER);
}
},
0,
ConstantsUnit.GENERATE_CUSTOMER*2,
TimeUnit.SECONDS);
}
}
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------