银行业务调度系统
模拟实现银行业务调度系统逻辑,具体需求如下:
Ø 银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。
Ø 有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。
Ø 异步随机生成各种类型的客户,生成各类型用户的概率比例为:
VIP客户 :普通客户 :快速客户 = 1 :6 :3。
Ø 客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需的时间,快速客户办理业务所需时间为最小值(提示:办理业务的过程可通过线程Sleep的方式模拟)。
Ø 各类型客户在其对应窗口按顺序依次办理业务。
Ø 当VIP(6号)窗口和快速业务(5号)窗口没有客户等待办理业务的时候,这两个窗口可以处理普通客户的业务,而一旦有对应的客户等待办理业务的时候,则优先处理对应客户的业务。
Ø 随机生成客户时间间隔以及业务办理时间最大值和最小值自定,可以设置。
定义枚举类,描述出三种类型的客户
1: ackage src.com.isoftstone.interview.bank;
2:
3: public enum CustomerType
4: {
5: COMMON,EXPRESS,VIP;
6: public String toString()
7: {
8: switch (this)
9: {
10: case COMMON:
11: return "普通";
12: case EXPRESS:
13: return "快速";
14: case VIP:
15: return "大户";
16: }
17: return null;
18: }
19: }
把之后要用到的所有常量封装成类
1: package src.com.isoftstone.interview.bank;
2:
3: public class Constants
4: {
5: public static int MAX_SERVICE_TIME=10000;
6: public static int MIN_SERVICE_TIME=1000;
7: public static int COMMON_CUSTOMER_INTERVAL_TIME=1;
8: }
定义一个专门生产号码和取号的管理器
1: package src.com.isoftstone.interview.bank;
2:
3: import java.util.ArrayList;
4: import java.util.List;
5: //定义一个号码管理器
6: public class NumberManager
7: {
8: //定义一个初始号,从1开始给号
9: private int lastNumber=1;
10: //定义存放所产生的序列号的集合
11: private List<Integer> queueNumbers=new ArrayList<Integer>();
12: //定义产生号方法,每产生一个序列号就存入集合中,号码自动顺延
13: public synchronized Integer generateNewManager()//产生号
14: {
15: queueNumbers.add(lastNumber);//存号
16: return lastNumber++;
17: }
18: //定义取号方法,返回值是取走的号,为了防止没取到号返回Null,而null转成int会发生空指针异常
19: //所以返回值类型定义为Integer
20: public synchronized Integer fetchNumber(){
21: if(queueNumbers.size()>0){
22: return (Integer)queueNumbers.remove(0);
23: }else{
24: return null;
25: }
26: }
27: //为防止产号和取号时操作共有数据会产生安全问题,用线程锁来控制
28:
29: }
有了号码管理器后,还需要一个号码生成器,由于三种客户数量不一样,因此三种客户每种生产的
号的方式也不一样,所以这个号码生产器就是根据管理器产生出三中不同的号管理器,并返回
1: package src.com.isoftstone.interview.bank;
2:
3: public class NumberMachine//返回三个不同的号管理器,这个总管理器必须只有一个(单例设计模式)
4: {
5: //单例设计模式的书写标准
6: private NumberMachine()
7: {
8: }
9: private static NumberMachine instance=new NumberMachine();
10: public static NumberMachine getInstance()
11: {
12: return instance;
13: }
14:
15: private NumberManager commonManager=new NumberManager();
16: private NumberManager expressManager=new NumberManager();
17: private NumberManager vipManager=new NumberManager();
18: public NumberManager getCommonManager() {
19: return commonManager;
20: }
21: public NumberManager getExpressManager() {
22: return expressManager;
23: }
24: public NumberManager getVipManager() {
25: return vipManager;
26: }
27:
28:
29: }
定义服务窗口类:三种类型的窗口对应的是三种不同的服务方式
1: package src.com.isoftstone.interview.bank;
2:
3: import java.util.Random;
4: import java.util.concurrent.Executors;
5: //服务窗口类
6: public class ServiceWindow
7: {
8: //定义客户类型为普通客户
9: private CustomerType type =CustomerType.COMMON;
10: public void setType(CustomerType type) {
11: this.type = type;
12: }
13: public void setWindowId(int windowId) {
14: this.windowId = windowId;
15: }
16: //服务从1号窗口开始,喊号
17: private int windowId=1;
18: public void start()
19: {
20: Executors.newSingleThreadExecutor().execute(new Runnable()
21: {
22: public void run()
23: {
24: while(true)
25: {
26: switch (type)
27: {
28: //分配普通客户的号
29: case COMMON://这里的结束符号是冒号,不是分号,注意!!
30: commonService();
31:
32: break;
33: case EXPRESS:
34: expressService();
35: break;
36: case VIP:
37: VipService();
38: break;
39: }
40: }
41: }
42: }
43: );
44: }
45:
46:
47:
48: private void commonService() {
49: String windowName="第"+windowId+"号"+type+"窗口";
50: System.out.println(windowName+"正在等待普通客户来");
51: Integer serviceNumber=NumberMachine.getInstance().getCommonManager().fetchNumber();
52: if(serviceNumber!=null)
53: {
54: System.out.println(windowName+"为第"+serviceNumber+"个"+type+"客户服务");
55: long beginTime=System.currentTimeMillis();
56: int maxRand=Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME;
57: long serveTime=new Random().nextInt(maxRand)+1+Constants.MIN_SERVICE_TIME;
58: try {
59: Thread.sleep(serveTime);//休息的时间
60: } catch (Exception e) {
61: // TODO: handle exception
62: }
63: long costTime=System.currentTimeMillis()-beginTime;
64: System.out.println(windowName+"为第"+serviceNumber+"个"+type+"客户完成服务,耗时:"+costTime/1000+"秒");
65: }
66: else
67: {
68: System.out.println(windowName+"没有人来,休息一秒");
69: try
70: {
71: Thread.sleep(1000);
72: }
73: catch (Exception e)
74: {
75: // TODO: handle exception
76: }
77: }
78: }
79:
80:
81:
82: private void expressService() {
83: String windowName="第"+windowId+"号"+type+"窗口";
84: System.out.println(windowName+"正在等待人来");
85: Integer serviceNumber=NumberMachine.getInstance().getExpressManager().fetchNumber();
86: if(serviceNumber!=null)
87: {
88: System.out.println(windowName+"为第"+serviceNumber+"个"+type+"客户服务");
89: long beginTime=System.currentTimeMillis();
90: //int maxRand=Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME;
91: // long serveTime=new Random().nextInt(maxRand)+1+Constants.MIN_SERVICE_TIME;
92: try {
93: Thread.sleep(Constants.MIN_SERVICE_TIME);//休息的时间
94: } catch (Exception e) {
95: // TODO: handle exception
96: }
97: long costTime=System.currentTimeMillis()-beginTime;
98: System.out.println(windowName+"为第"+serviceNumber+"个"+type+"客户完成服务,耗时:"+costTime/1000+"秒");
99: }
100: else
101: {
102: System.out.println(windowName+"没有人来,休息一秒");
103: commonService();
104: }
105: }
106:
107: private void VipService() {
108: String windowName="第"+windowId+"号"+type+"窗口";
109: System.out.println(windowName+"正在等待人来");
110: Integer serviceNumber=NumberMachine.getInstance().getVipManager().fetchNumber();
111: if(serviceNumber!=null)
112: {
113: System.out.println(windowName+"为第"+serviceNumber+"个"+type+"客户服务");
114: long beginTime=System.currentTimeMillis();
115: int maxRand=Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME;
116: long serveTime=new Random().nextInt(maxRand)+1+Constants.MIN_SERVICE_TIME;
117: try {
118: Thread.sleep(serveTime);//休息的时间
119: } catch (Exception e) {
120: // TODO: handle exception
121: }
122: long costTime=System.currentTimeMillis()-beginTime;
123: System.out.println(windowName+"为第"+serviceNumber+"个"+type+"客户完成服务,耗时:"+costTime/1000+"秒");
124: }
125: else
126: {
127: System.out.println(windowName+"没有大户来");
128: commonService();//没大户的时候就去给普通客户服务
129: //System.out.println("大户窗口为普通客户服务");
130: }
131:
132: }
133: }
定义程序开始类,主要是产生6个窗口,并控制号码产生器,来3个线程同时产生不同类型的客户号
1: package src.com.isoftstone.interview.bank;
2:
3: import java.util.concurrent.Executors;
4: import java.util.concurrent.TimeUnit;
5:
6: public class MainClass
7: {
8: public static void main(String[] args)
9: {
10: //产生4个普通窗口
11: for(int i=1;i<5;i++)
12: {
13: ServiceWindow commonWindow=new ServiceWindow();
14: commonWindow.setWindowId(i);
15: commonWindow.start();
16: }
17: //产生1个快速窗口
18: ServiceWindow expressWindow=new ServiceWindow();
19: expressWindow.setType(CustomerType.EXPRESS);
20: expressWindow.setWindowId(5);
21: expressWindow.start();
22: //产生1个VIP窗口
23: ServiceWindow VipWindow=new ServiceWindow();
24: VipWindow.setType(CustomerType.VIP);
25: VipWindow.setWindowId(6);
26: VipWindow.start();
27: //普通客户拿号
28: Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
29: new Runnable(){
30: public void run()
31: {
32: //号码产生器的实例对象调用一个能产生普通客户号的号码控制器,并产生一个普通客户号
33: Integer number =NumberMachine.getInstance().getCommonManager().generateNewManager();
34: //打印一下,一个普通客户来了
35: System.out.println(number+"号普通客户在等");
36: }
37: },
38: 0,//马上就产生这个号
39: Constants.COMMON_CUSTOMER_INTERVAL_TIME, //普通客户服务时间到了之后再产生下一个
40: TimeUnit.SECONDS
41: );
42: //同理,大客户来了
43: Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
44: new Runnable(){
45: public void run()
46: {
47: Integer number =NumberMachine.getInstance().getVipManager().generateNewManager();
48: System.out.println(number+"号客户在等");
49: }
50: },
51: 0,
52: Constants.COMMON_CUSTOMER_INTERVAL_TIME*6, //大户六秒来一个
53: TimeUnit.SECONDS
54: );
55: //快速客户来了
56: Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
57: new Runnable(){
58: public void run()
59: {
60: Integer number =NumberMachine.getInstance().getExpressManager().generateNewManager();
61: System.out.println(number+"号快速客户在等");
62: }
63: },
64: 0,
65: Constants.COMMON_CUSTOMER_INTERVAL_TIME*2, //大户六秒来一个
66: TimeUnit.SECONDS
67: );
68:
69:
70: }
71:
72: }