张孝祥视频里的银行业务调度系统,需求与分析这里略过,网上很容易就找得到这方面的资料。这里谈谈其中的ServiceWindow类。
ServiceWindow类
定义一个start方法,内部启动一个线程,根据服务窗口的类别分别循环调用三个不同的方法。
定义三个方法分别对三种客户进行服务,为了观察运行效果,应详细打印出其中的细节信息。
代码中有说明:没有把VIP窗口和快速窗口做成子类,是因为实际业务中的普通窗口可以随时被设置为VIP窗口和快速窗口。
由于三个不同窗口的方法,里面的代码有许多类同的,所以试着把它重构成一个Service 方法:
private void Service(String typeStr,Integer serviceNumber){
String windowName = "第" + number + "号" + typeStr + "窗口";
System.out.println(windowName + "开始获取" + typeStr + "任务!");
if(serviceNumber != null ){
System.out.println(windowName + "开始为第" + serviceNumber + "号" + typeStr + "客户服务");
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(windowName + "完成为第" + serviceNumber + "号" + typeStr + "客户服务,总共耗时" + serviceTime/1000 + "秒");
}else{
System.out.println(windowName + "没有取到" + typeStr + "任务");
switch(type){
case COMMON:
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
case EXPRESS:
Service("普通",serviceNumber);
break;
case VIP:
Service("普通",serviceNumber);
break;
}
}
}
未运行前,也觉得这样不妥,因嵌套调用Service 方法,这变成递归了!结果一运行,就有问题了,不行。之后改成下面的:
public void start(){
Executors.newSingleThreadExecutor().execute(
new Runnable(){
public void run(){
//下面这种写法的运行效率低,最好是把while放在case下面
Integer serviceNumber;
while(true){
switch(type){
case COMMON:
serviceNumber= NumberMachine.getInstance().getCommonManager().fetchNumber();
Service("普通",serviceNumber);
break;
case EXPRESS:
serviceNumber = NumberMachine.getInstance().getCommonManager().fetchNumber();
Service("快速",serviceNumber);
break;
case VIP:
serviceNumber = NumberMachine.getInstance().getCommonManager().fetchNumber();
Service("VIP",serviceNumber);
}
}
}
}
);
}
private boolean flagExpress=true;
private boolean flagVIP=true;
private void Service(String typeStr,Integer serviceNumber){
String windowName = "第" + number + "号" + typeStr + "窗口";
System.out.println(windowName + "开始获取" + typeStr + "任务!");
if(serviceNumber != null ){
System.out.println(windowName + "开始为第" + serviceNumber + "号" + typeStr + "客户服务");
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(windowName + "完成为第" + serviceNumber + "号" + typeStr + "客户服务,总共耗时" + serviceTime/1000 + "秒");
}else{
System.out.println(windowName + "没有取到" + typeStr + "任务");
switch(type){
case COMMON:
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
case EXPRESS:
if(flagExpress) Service("普通",serviceNumber);
flagExpress=false;
break;
case VIP:
if(flagVIP) Service("普通",serviceNumber);
flagExpress=false;
break;
}
}
}
想通过一标记,控制调用Service 方法,就是这递归有条件的,不会无限循环,可惜不行,可能是多线程的原因吧。后来找了些资料,再上网Search,有人这样做:
private void service(CustomerType customerType, String windowName,
Integer number, long elapsedTime) {
String customerName = "第" + number +"号" + customerType +"客户";
System.out.println(windowName + "正在为" + customerName + "服务。");
try {
Thread.sleep(elapsedTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(windowName + "完成对" + customerName + "的服务,耗时" +(elapsedTime/1000) +"秒");
}
private void expressService(ServiceWindow window) {
CustomerType customerType = CustomerType.EXPRESS;
String windowName = "第" + window.windowID +"号" + window.windowType +"窗口";
Integer number = NumberMachine.expressNumber.fetchNumer();
if(number != null)
{
long elapsedTime = Constants.MIN_SERVICE_TIME;
service(customerType, windowName, number, elapsedTime);
}
else
{
commonService(window);
}
}
他没把三个方法全部合在一个,只是把其中部分代码放到service,之后三个方法再调用service,参考上面我贴出的expressService,就是只将三个方法内类同的代码做成一方法。看来我太“大贪”了,想三合一,起码这里是很困难的。