-------android培训,java培训、期待与您交流-------
学习了张老师的银行业务调度系统,对多线程的程序有了一个新的了解,具体的来说,就是模拟了一个银行窗口的业务调度。而从张老师的代码里,可以看到有很多的java知识点存在,这里面涉及到:枚举,单例,多线程,线程定时器,对象的封装,以及面向接口编程。
下面让我们来看下具体的业务逻辑。
1 银行内有6个业务窗口,1- 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。
2 有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。
3 异步随机生成各种类型的客户,生成各类型用户的概率比例为:
VIP客户 :普通客户 :快速客户 = 1 :6 :3。
4 客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需的时间,快速客户办理业务所需时间为最小值(提示:办理业务的过程可通过线程Sleep的方式模拟)。
5 各类型客户在其对应窗口按顺序依次办理业务。
6 当VIP(6号)窗口和快速业务(5号)窗口没有客户等待办理业务的时候,这两个窗口可以处理普通客户的业务,而一旦有对应的客户等待办理业务的时候,则优先处理对应客户的业务。
在张老师的代码的基础上,我将代码做了一些修改。主要就是简化了它的代码。
首先:因为原来的号码生成器是一个单例模式,所以在服务窗口调用时候每次都需要获得该对象然后调用封装的Manager,这样使代码过于繁琐,鉴于此,我创建了一个工厂类,通过客户的类型,来分别调用单例模式里面的封装的对象
来调用对应的处理方法
//号码生成器工厂
public class FactoryNumberMachine {
//获取等待客户
public static Integer getNumber(CustomerType type) {
return getNumberManager(type).generateNewNumber();
}
//根据客户类型获得对应的NumberManager
private static NumberManager getNumberManager(CustomerType type) {
switch (type) {
case COMMON:
return NumberMachine.getInstance().getCommonManager();
case VIP:
return NumberMachine.getInstance().getVipManager();
case QUICK:
return NumberMachine.getInstance().getExpressManager();
}
return null;
}
//处理客户请求
public static Integer fetchNumer(CustomerType type) {
return getNumberManager(type).fetchNumber();
}
}
//服务窗口
public class ServiceWindow {
//初始化类型为普通类型
private CustomerType type = CustomerType.COMMON;
//初始化窗口编号为1
private int windowID = 1;
//初始化是否选择普通类型为false
private boolean isChange = false;
public boolean isChange() {
return isChange;
}
public void setChange(boolean isChange) {
this.isChange = isChange;
}
public CustomerType getType() {
return type;
}
public void setType(CustomerType type) {
this.type = type;
}
public void setwindowID(int windowID){
this.windowID = windowID;
}
//通过线程池来调用allService方法
public void start(){
Executors.newSingleThreadExecutor().execute(
new Runnable(){
public void run(){
while(true){
allService(isChange);
}
}
}
);
}
//执行服务的方法
private void allService(boolean isChange) {
//根据窗口编号和类型生成对应的提示字符串
String windowName = "第"+windowID+"号"+type+"窗口";
Integer number = null;
//根据是否改变为普通类型判断调用对应的执行服务的方法,如果为true则传入普通类型,否则传入窗口类型
if(isChange){
number = FactoryNumberMachine.fetchNumer(CustomerType.COMMON);
}else{
number = FactoryNumberMachine.fetchNumer(type);
}
System.out.println(windowName+"正在获取任务");
//如果获取到客户则开始为客户服务,利用线程休眠方法让程序执行有间隔,并计算出时间既为服务耗时
if(number != null){
long beginTime = System.currentTimeMillis();
int maxServerTime = new Random().nextInt(Constants.MAX_SERVER_TIME)+1;
try {
Thread.sleep(maxServerTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long costTime = System.currentTimeMillis()-beginTime;
//根据是否改变为普通类型打印对应的服务输出语句
if(isChange){
System.out.println(windowName+"为第"+number+"个"+CustomerType.COMMON+"客户完成服务,耗时"+costTime/1000+"秒");
}else{
System.out.println(windowName+"为第"+number+"个"+type+"客户完成服务,耗时"+costTime/1000+"秒");
}
}else{
//如果没有取到服务的客户则休息一会,然后根据类型判断,如果类型不是普通类型,则将是否改变为普通类型置为true并递归调用allService方法
System.out.println(windowName+"没有取到服务任务!! 先休息一秒钟嘛!!");
try {
Thread.sleep(Constants.MIN_SERVER_TIME);
if(type != CustomerType.COMMON)isChange = true;
allService(isChange);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}