银行业务的调度问题,咋一看感觉不难,但是真的要下手还真不知道应该从哪个方面开始。我看了好几遍,老师编码的过程,才算是有点明白了。这个主要是用到了线程的部分知识。从需求分析来看,就是说客户来后通过号码机获得自己所需要的类型的服务,比如普通客户的服务,快速客户的服务以及VIP客户的服务。那么对应的窗口就应该同样有这三种类型的服务窗口了。一般来说普通窗口的用户最多,那么对应的这种窗口就必须最多。在需求中,要求每隔一秒就要有一个普通用户等待服务,而快速用户则是在2秒的时候来一位,至于VIP则是6秒来一位。在快速窗口和VIP窗口没有获得相应的任务的时候,应该可以接受来自需要服务的普通用户。
现在的设计,从上面分析可以看出来,首先有一个号码产生器,这个产生器可以产生3种不同类型的号码。通过这个号码,窗口进行调用。那么我们就要一个类,这个类是号码产生器,并且唯一,可以用单例的模式来实现。而三种号码,应该有相应的 类来生成。统一来定义一个号码管理的类,然后再号码产生器中声明3个这种类的对象就可以了。这个号码生成后,就要通过服务窗口来调用并服务了,我们把这个服务用线程的sleep来实现。窗口的类型我们也必须知道,通过一个枚举类型来声明,在设置这个窗口类型的时候我们可以调用这个类的set方法来设置。同样由于普通窗口有多个,那么我们就要给每一个窗口来设置一个窗口号码,可以方便辨别,去什么类型窗口的几号去要求服务。这两个属性都有相应的set方法。最后就是在MainClass中模拟了,首先我们要把服务窗口new出来,同时把两个属性都通过set方法来设置好。然后就是通过号码管理器来生成不同类型客户的服务号码了。这里我们要使用线程的定时功能来实现这个模拟。对于3种类型的客户有3个线程来实现。
号码生成器,和号码管理器的代码:
import java.util.ArrayList;
import java.util.List;
public class NumberManager {
private List<Integer> numberQueue = new ArrayList<Integer>();
private int lastNumber = 1;
public synchronized Integer generateNewNumber(){
//获得服务号码
numberQueue.add(lastNumber);
//添加到服务队列中
return lastNumber ++;
}
public synchronized Integer fetchNumber(){
Integer number = null;
if(numberQueue.size()>0)
//如果这个服务队列中有元素就把这个元素返回
number = numberQueue.remove(0);
return number;
}
}
public class NumberMachine {//对号码管理器进行统一管理
private NumberManager commonManager = new NumberManager();
//普通号码管理器
private NumberManager quickManager= new NumberManager();
//快速号码管理器
private NumberManager vipManager= new NumberManager();
//vip号码管理器
public NumberManager getCommonManager() {
return commonManager;
}
public NumberManager getQuickManager() {
return quickManager;
}
public NumberManager getVipManager() {
return vipManager;
}
//该号码产生器是只有需要一个实例所以使用单例的模式
private NumberMachine(){}
public static NumberMachine getInstance(){
return instance;
}
private static NumberMachine instance = new NumberMachine();
}
服务窗口的主要代码:
public class ServiceWindow {
private CustomerType type = CustomerType.COMMON;
//窗口类型
private int windowId = 1;
public void start(){
//用于控制对于不同用户进行服务的线程
Executors.newSingleThreadExecutor().execute(new Runnable(){
public void run(){
while(true){
switch(type){
case COMMON:
commonSever();
break;
case QUICK:
quickSever();
break;
case VIP:
vipSever();
break;
}}} }); }
commonSever();quickSever();vipSever();
这三个方法实现的时候比较相似,主要是获得服务号,并服务,这里就不列出来了。最后就是MainClass了,这个主要是看这个模拟过程是不是可以:
public class MainClass {
public static void main(String[] args) {
for(int i=1;i<5;i++){
//声明4个普通窗口
ServiceWindow commonWindow = new ServiceWindow();
commonWindow.setWindowId(i);
commonWindow.start();
}
ServiceWindow quickWindow = new ServiceWindow();
//new快速服务窗口
quickWindow.setWindowId(5);
//设置窗口号码
quickWindow.setType(CustomerType.QUICK);
//设置窗口类型
quickWindow.start();
ServiceWindow vipWindow = new ServiceWindow();
//newVIP服务窗口
vipWindow.setWindowId(6);
vipWindow.setType(CustomerType.VIP);
vipWindow.start();
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(//普通客户号码获取
new Runnable(){
public void run(){
synchronized (CustomerType.COMMON) {
Integer number = NumberMachine.getInstance()
.getCommonManager().generateNewNumber();
System.out.println("第" + number + "号普通客户等待服务!!!");
}
}
},
0,
Constants.COMMON_CUSTOMER_INTERVAL_TIME,
TimeUnit.SECONDS);
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(//快速客户号码获取
new Runnable(){
public void run(){
synchronized (CustomerType.QUICK) {
Integer number = NumberMachine.getInstance()
.getQuickManager().generateNewNumber();
System.out.println("第" + number + "号快速客户等待服务!!!");
}
}
},
0,
Constants.COMMON_CUSTOMER_INTERVAL_TIME*2,
TimeUnit.SECONDS);
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(//vip客户号码获取
new Runnable(){
public void run(){
synchronized (CustomerType.VIP) {
Integer number = NumberMachine.getInstance()
.getVipManager().generateNewNumber();
System.out.println("第" + number + "号VIP客户等待服务!!!");
}
}
},
0,
Constants.COMMON_CUSTOMER_INTERVAL_TIME*6,
TimeUnit.SECONDS);
}
}
这3个定时器,用于控制不同用户出现的数量,使得数量比是1:6:3.
今天为止,这个视频终于看完了,至于什么感想吧,觉得自己还有好多没有学明白,还要继续努力呀。