------- android培训、java培训、期待与您交流! ----------
在做银行业务调度系统这个题目的时候,我们是需要了解一下银行业务办理的流程的:
通常情况下是这样的,我们去银行取钱的时候,需要先去取号机器上取号(就相当于我们站在服务窗口前排队一样,只是有了取号机器,它知道用户取到了哪个号码为止了,而服务窗口就根据我们的取的号码来依次为我们服务)所以通过上面的分析,我们知道,在整个银行里面只有一个号码机器,而银行的业务窗口又分为普通,快速(这个可以办理交水电费和还贷的业务),VIP(钱多的可以用这个)
快速窗口和VIP窗口,它们在没有业务的时候也是可以帮普通的客户进行服务的。
所以,我们总结了一下,这里的对象,应该有如下几个:
号码管理器: 它的作用是管理它所产生号码:
它有两个用处:
一个是提供号码给客户取号,排队使用。
一个是提供号码给服务窗口使用,因为服务窗口要从号码管理器那里知道该为哪个客户服务了。
号码机器:
它的内部管理了三种类型的号码管理器,普通,快速,VIP。三种
因为在整个银行中,只有一台号码机器。所以它在程序中设计的时候是要做成单例的。
然后就是服务窗口,它要根据自己是哪种类型的窗口去找号码机器,找它里面的号码管理器。问他该为哪个号码服务了。 这里在设计号码管理器的时候,是通过集合的形式来实现的。因为号码机器产生了号码之后,用户会取走一个号码,然后再产生就是下一个数了,我们在用户取号的时候,把用户取走的那个号码按队列的形式添加到这个集合中,而服务窗口在取号的时候,就是从集合中取的。服务窗口在取号的时候,是从队列的第0个位置开始取走的。即取走了集合中的第一个元素。
因为号码管理器中,是两个方法都是在操作同一个集合,所以我们要让两个方法互斥,即同时只能有一个方法操作集合。
----------------------------------------------------
需要注意的细节如下:
我们在这个题目中是使用JDK 1.5的那套线程库,我们使用的Executors并发库。
线程池
Executors.newSingleThreadExecutor().execute(new Runnable() {@Override
public void run() {
//线程所要执行的任务
}
});
开启了一个线程池,线程池中只有一个线程,我们是把任务交给线程池,由线程池去池中挑选空闲的线程,把任务交给他去执行。而不是我们把任务直接交给某个线程去执行。
调度池
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
int number = NumberMachine2.getInstance().getCommonManager()
.genrateNewNumber();
System.out.println(number + "号普通客户等待服务");
}
}, 0, Constants2.INTERVAL_TIME2, TimeUnit.SECONDS);
这里列出一个调度池,里面是用于定时调度的,它可以定于某个时间干一件事情,也可以定在一段时间干一件之后,然后再过一段时间再执行这件事情。这有点像生活中的定时炸弹的原理。
----------------------------------------------------
在模拟客户进入营业厅的时候,分析如下:
vip:express:common
6: 2: 1
我们这么来分析:普通客户来2个,快速客户来1个
普通客户来6个,VIP客户才来1个。
我们在模拟给服务服务的时候,是让线程随机进行休眠的,是使用随机数来实现的,随机数中的nextInt的值是取于10000-1000的即最大随机数,9000,使用随机数之后起作用的就是0-8999,然后+1即1-9000,然后+1000即1-10000
----------------------------------------------------
因为我们的服务窗口只有三种类型的:普通,快速,VIP我们可以使用枚举来操作 我们使用name()它的作用是返回此枚举变量的名称,就是我们在枚举类中定义的变量的名称
-------------------------------------------------------------------------
public class NumberManager2 {
private List<Integer> queue = new ArrayList<Integer>();
private int lastNumber = 1;
public synchronized Integer genrateNewNumber() {
queue.add(lastNumber);
return lastNumber++; //第一次返回1,第二次返回2
}
public synchronized Integer featchNumber() {
Integer number=null;
if(queue.size()>0){
number=queue.remove(0);
}
return number;
}
}
public class NumberMachine2 {
private NumberManager2 commonManager = new NumberManager2();
private NumberManager2 expressManager = new NumberManager2();
private NumberManager2 vipManager = new NumberManager2();
public NumberManager2 getCommonManager() {
return commonManager;
}
public NumberManager2 getExpressManager() {
return expressManager;
}
public NumberManager2 getVipManager() {
return vipManager;
}
private NumberMachine2() {
}
public static NumberMachine2 getInstance() {
return instance;
}
private static NumberMachine2 instance = new NumberMachine2();
}
public class ServiceWindow2 {
private Customer2Type type = Customer2Type.COMMON; // 窗口的类型
private int windowId = 1; // 窗口的编号
public void setType(Customer2Type type) {
this.type = type;
}
public void setWindowId(int windowId) {
this.windowId = windowId;
}
public void start() {
Executors.newSingleThreadExecutor().execute(new Runnable() {
@Override
public void run() {
while (true) {
switch (type) {
case COMMON:
commonService();
break;
case EXPRESS:
expressService();
break;
case VIP:
vipService();
break;
}
}
}
});
}
// 普通客户
private void commonService() {
Integer number = NumberMachine2.getInstance().getCommonManager()
.featchNumber();
System.out.println("第" + windowId + "个" + type + "窗口开始获取普通任务");
// System.out.println("commonservicenumber:" + number);
if (number != null) {
System.out.println("第" + windowId + "个" + type + "窗口准备为第" + number
+ "个普通客户服务");
long beginServiceTime2 = System.currentTimeMillis();
int maxRandom = Constants2.MAX_SERVICE_TIMES
- Constants2.MIN_SERVICE_TIMES;
long serviceTimes2 = new Random().nextInt(maxRandom) + 1
+ Constants2.MIN_SERVICE_TIMES;
try {
Thread.sleep(serviceTimes2);
} catch (InterruptedException e) {
e.printStackTrace();
}
long coastServiceTime2 = System.currentTimeMillis()
- beginServiceTime2;
System.out.println("第" + windowId + "个" + type + "窗口准备为第" + number
+ "个普通客户完成服务,耗时:" + coastServiceTime2 / 1000 + "秒");
} else {
System.out.println("第" + windowId + "个" + type
+ "窗口没有获取到普通任务,需要休息1秒");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 快速客户
private void expressService() {
String windowName = "第" + windowId + "个" + type + "窗口";
Integer number = NumberMachine2.getInstance().getExpressManager()
.featchNumber();
System.out.println(windowName + "开始获取快速业务");
// System.out.println("expressServiceNumber:" + number);
if (number != null) {
System.out.println(windowName + "准备为第" + number + "个快速客户服务");
long beginServiceTime2 = System.currentTimeMillis();
// int maxRandom = Constants2.MAX_SERVICE_TIMES
// - Constants2.MIN_SERVICE_TIMES;
// long serviceTimes2 = new Random().nextInt(maxRandom) + 1
// + Constants2.MIN_SERVICE_TIMES;
try {
Thread.sleep(Constants2.MIN_SERVICE_TIMES);
} catch (InterruptedException e) {
e.printStackTrace();
}
long coastServiceTime2 = System.currentTimeMillis()
- beginServiceTime2;
System.out.println("第" + windowId + "个" + type + "窗口准备为第" + number
+ "个快速客户完成服务,耗时:" + coastServiceTime2 / 1000 + "秒");
} else {
System.out.println("第" + windowId + "个" + type
+ "窗口没有获取到快速任务,可以为普通用户服务");
commonService();
}
}
// VIP客户
private void vipService() {
String windowName = "第" + windowId + "个" + type + "窗口";
Integer number = NumberMachine2.getInstance().getVipManager()
.featchNumber();
System.out.println(windowName + "开始获取VIP业务");
// System.out.println("vipServiceNumber:" + number);
if (number != null) {
System.out.println(windowName + "准备为第" + number + "个VIP客户服务");
long beginServiceTime2 = System.currentTimeMillis();
int maxRandom = Constants2.MAX_SERVICE_TIMES
- Constants2.MIN_SERVICE_TIMES;
long serviceTimes2 = new Random().nextInt(maxRandom) + 1
+ Constants2.MIN_SERVICE_TIMES;
try {
Thread.sleep(serviceTimes2);
} catch (InterruptedException e) {
e.printStackTrace();
}
long coastServiceTime2 = System.currentTimeMillis()
- beginServiceTime2;
System.out.println("第" + windowId + "个" + type + "窗口准备为第" + number
+ "个VIP客户完成服务,耗时:" + coastServiceTime2 / 1000 + "秒");
} else {
System.out.println("第" + windowId + "个" + type
+ "窗口没有获取到VIP任务,可以为普通用户服务");
commonService();
}
}
}
public class Constants2 {
public static int MAX_SERVICE_TIMES=10000;
public static int MIN_SERVICE_TIMES=1000;
public static int INTERVAL_TIME2=1;
}
public enum Customer2Type {
COMMON, EXPRESS, VIP;
public String toString(){
switch(this){
case COMMON:
return "普通";
case EXPRESS:
return "快速";
case VIP:
return name();
}
return null;
}
}
/**
* @param args
*/
public static void main(String[] args) {
// 创建窗口对象
for (int i = 1; i < 5; i++) {
ServiceWindow2 commonServcie = new ServiceWindow2();
commonServcie.setWindowId(i);
commonServcie.start();
}
ServiceWindow2 expressService = new ServiceWindow2();
expressService.setType(Customer2Type.EXPRESS);
expressService.start();
ServiceWindow2 vipService = new ServiceWindow2();
vipService.setType(Customer2Type.VIP);
vipService.start();
// 模拟客户
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
int number = NumberMachine2.getInstance().getCommonManager()
.genrateNewNumber();
System.out.println(number + "号普通客户等待服务");
}
}, 0, Constants2.INTERVAL_TIME2, TimeUnit.SECONDS);
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
int number = NumberMachine2.getInstance().getExpressManager()
.genrateNewNumber();
System.out.println(number + "号快速客户等待服务");
}
}, 0, Constants2.INTERVAL_TIME2 * 2, TimeUnit.SECONDS);
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
int number = NumberMachine2.getInstance().getVipManager()
.genrateNewNumber();
System.out.println(number + "号VIP客户等待服务");
}
}, 0, Constants2.INTERVAL_TIME2 * 6, TimeUnit.SECONDS);
}