模拟银行调度系统需求:
银行有6个业务窗口
1-4为普通窗口,5号窗口为快速窗口6号为VIP窗口
异步随机生成各种类型的客户,生成各种客户的比例为
VIP客户:普通客户:快速口=1:6:3
客户办理业务所需的时间不同,所以要设置所需时间的最大值和最小值.这个值只设定在VIP客户与普通客户.快速客户所需的时间总为1秒
各种类型的客户在各自的窗口办理业务
VIP窗口与快速窗口优先于办理自己类型的可以.当空闲的时候可以办理普通业务
面向对象的设计.
号码管理的机器NumberMchine
分别管理普通用户号码(getCommonManager)快速客户(getExpressManager)VIP客户(getVIPManager)管理器是唯一的所以管理器设计为单例,所以提供获取管理器的方法getinstance
号码产生机器
NumberManager 产生3中类型的客户号码generateNumber(),提供当前需要服务客户的号码给窗口fetchNumber()
服务窗口ServiceWindow
CommonService()//普通客户服务窗口
experssService()//快速客户服务窗口
VIPService(()//VIP服务窗口
开启窗口服务的方法 start()
下面是我看张老师视频自己,并加上了自己的理解,错误的地方希望老师给出批评
//号码产生器NumberManager
package BANK_Demo;
import java.util.ArrayList;
import java.util.List;
public class NumberManager {
private int lastNumber = 1;
private List <Integer> queueNumber = new ArrayList<Integer>();
//不断的产生号码.
public synchronized Integer generateNumber(){//后面会使用异步产生客户,使用到多线程,而且有共同的数据(集合里面的号码)所以这里使用同步函数
queueNumber.add(lastNumber);
return lastNumber++;
}
public synchronized Integer fetchSreviceNumber(){
Integer number = null;
if(queueNumber.size()>0){
number = queueNumber.remove(0);
}
return number;
}
}
//管理三种不同类型客户号码机器NumberMchine
package BANK_Demo;
public class NumberMchine {
//同一个号码管理器管理三种不同类型的号码.
private NumberManager commonManager = new NumberManager();
private NumberManager experssManager = new NumberManager();
private NumberManager vipManager = new NumberManager();
public NumberManager getCommonManager() {
return commonManager;
}
public NumberManager getExperssManager() {
return experssManager;
}
public NumberManager getVipManager() {
return vipManager;
}
private NumberMchine(){}
public static NumberMchine getinstance(){
return instance;
}
private static NumberMchine instance = new NumberMchine();
}
//定义三种类型客户,为特定所以使用枚举
package BANK_Demo;
public enum CustomerType {
//只有三种客户的类型,所以定义为枚举.
COMMON,EXPERSS,VIP;
//重写toString方法,打印我们熟悉的值,就是当出现COMMON的时候大意普通客户.
public String toString(){
switch(this){//这里的this为type.因为不确定type到底是COMMON,EXPERSS,VIP所以这里使用ths关键字.
case COMMON:
return "普通";
case EXPERSS:
return "快速";
case VIP:
return "VIP";
}
return null;
}
}
//Constants定义常量.定义服务花费的时间的最大值与最小值,张孝祥老师说常量最好单独定义.所以我今后也得养成这个习惯
package BANK_Demo;
public class Constants {
//创建服务花费的时间,为1秒到10秒之间的数定义为常量
public static int MAX_SERVICE_TIME = 10000;
public static int MIN_SERVICE_TIME = 1000;
}
//定义服务窗口ServiceWindow,这也是最难理解的一段代码.
package BANK_Demo;
import java.util.Random;
import java.util.concurrent.Executors;
public class ServiceWindow {
private CustomerType type = CustomerType.COMMON;//定义默认的窗口为普通窗口
private int window =1;//定义默认的窗口号
public void setType(CustomerType type) {//设置窗口
this.type = type;
}
public void setWindow(int window) {
this.window = window;//设置窗口好
}
public void start(){//启动程序
//产生一组线程,使程序不断的取号,服务.
Executors.newSingleThreadExecutor().execute(new Runnable(){
public void run() {
while(true){
switch(type){
case COMMON:
commonService();
break;
case EXPERSS:
experssService();
break;
case VIP:
vipService();
break;
}
}
}
});
}
public void commonService(){//定义普通窗口服务的方法
String windowName = "第"+window+"號"+type+"窗口";
//获取号码管理机器的对象,取得对应客户的类型.平且窗口叫号服务
Integer number = NumberMchine.getinstance().getCommonManager().fetchSreviceNumber();
//fetchSreviceNumber()是同步的,为了不干扰下面的输出语句,将输出语句放到后面
System.out.println(windowName+"正在獲取任務");
if(number!=null){//当号码存在的时候开始服务
System.out.println("第"+window+"號"+"普通"+"窗口"+"正在为第"+number+type+"客户服务");
long beginTime = System.currentTimeMillis();//开始服务的的时间
int maxRand =Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME;
long serveTima=new Random().nextInt(maxRand)+1+Constants.MIN_SERVICE_TIME;
try {
Thread.sleep(serveTima);
} catch (InterruptedException e) {
e.printStackTrace();
}
long costTime = System.currentTimeMillis()- beginTime;//服务消耗的时间等于服务完的时间减去开始服务的时间
System.out.println(windowName+"為第"+number+"個"+"普通"+"客戶完成服務,耗時"+costTime/1000+"秒");
}else{
System.out.println(windowName+"沒有取到任務,先休息1秒");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void experssService(){
String windowName = "第"+window+"號"+type+"窗口";
Integer number = NumberMchine.getinstance().getExperssManager().fetchSreviceNumber();
System.out.println(windowName+"正在獲取任務");
if(number!=null){
System.out.println("第"+window+"號"+type+"窗口"+"正在为第"+number+type+"客户服务");
long beginTime = System.currentTimeMillis();
//int maxRand =Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME;
//long serveTima=new Random().nextInt(maxRand)+1+Constants.MIN_SERVICE_TIME;
try {
Thread.sleep(Constants.MIN_SERVICE_TIME);
} catch (InterruptedException e) {
e.printStackTrace();
}
long costTime = System.currentTimeMillis()- beginTime;
System.out.println(windowName+"為第"+number+"個"+type+"客戶完成服務,耗時"+costTime/1000+"秒");
}else{
System.out.println(windowName+"沒有取到任務");
commonService();
}
}
public void vipService(){
String windowName = "第"+window+"號"+type+"窗口";
Integer number = NumberMchine.getinstance().getVipManager().fetchSreviceNumber();
System.out.println(windowName+"正在獲取任務");
if(number!=null){
System.out.println("第"+window+"號"+type+"窗口"+"正在为第"+number+type+"客户服务");
long beginTime = System.currentTimeMillis();
//int maxRand =Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME;
//long serveTima=new Random().nextInt(maxRand)+1+Constants.MIN_SERVICE_TIME;
try {
Thread.sleep(Constants.MIN_SERVICE_TIME);
} catch (InterruptedException e) {
e.printStackTrace();
}
long costTime = System.currentTimeMillis()- beginTime;
System.out.println(windowName+"為第"+number+"個"+type+"客戶完成服務,耗時"+costTime/1000+"秒");
}else{
System.out.println(windowName+"沒有取到任務");
commonService();
}
}
}
//定义主函数,对数据初始化
package BANK_Demo;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class MainClass {
public static void main(String[] args) {
//产生普通窗口
for (int i = 1; i < 5; i++) {
ServiceWindow commonWindow = new ServiceWindow();
commonWindow.setWindow(i);//普通窗口有4个设置窗口号
commonWindow.start();
}
//产生快速窗口
ServiceWindow experssWindow = new ServiceWindow();
experssWindow.setType(CustomerType.EXPERSS);//设置类型.快速窗口就是1个所以不用设置窗口号
//发现窗口的启动,只要一个窗口启动了,也是可以的.因为ServiceWindow类中的start()有三种类型的窗口.
//experssWindow.start();
ServiceWindow VIPWindow = new ServiceWindow();
VIPWindow.setType(CustomerType.VIP);
//VIPWindow.start();
// 创建一个控制器,异步产生客户
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
//每隔一秒创建一个普通客户
Integer number = NumberMchine.getinstance().getCommonManager().generateNumber();
System.out.println("第"+number+"普通客戶等待服務");
}
}, 0, 1, TimeUnit.SECONDS);
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
//每隔三秒创建一个快速客户
Integer number = NumberMchine.getinstance().getExperssManager().generateNumber();
System.out.println("第"+number+"快速客戶等待服務");
}
}, 0, 3, TimeUnit.SECONDS);
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
//每隔六秒创建一个VIP客户
public void run() {
Integer number = NumberMchine.getinstance().getVipManager().generateNumber();
System.out.println("第"+number+"VIP客戶等待服務");
}
}, 0, 6, TimeUnit.SECONDS);//这里还是不定义常量,我觉得这样好理解.但是扩展性不强.
}
}
---------------------- android培训、 java培训、期待与您交流! ----------------------