银行业务调度系统的实现
银行业务调度系统
模拟实现银行业务调度系统逻辑。详细需求例如以下:
银行内有6个业务窗体,1 - 4号窗体为普通窗体,5号窗体为高速窗体,6号窗体为VIP窗体。
有三种相应类型的客户:VIP客户,普通客户,高速客户(办理如交水电费、电话费之类业务的客户)。
异步随机生成各种类型的客户,生成各类型用户的概率比例为:
VIP客户 :普通客户 :高速客户 = 1 :6 :3。
客户办理业务所需时间有最大值和最小值,在该范围内随机设定每一个VIP客户以及普通客户办理业务所需的时间,高速客户办理业务所需时间为最小值(提示:办理业务的过程可通过线程Sleep的方式模拟)。
各类型客户在其相应窗体按顺序依次办理业务。
当VIP(6号)窗体和高速业务(5号)窗体没有客户等待办理业务的时候。这两个窗体能够处理普通客户的业务,而一旦有相应的客户等待办理业务的时候。则优先处理相应客户的业务。
随机生成客户时间间隔以及业务办理时间最大值和最小值自定,能够设置。
不要求实现GUI,仅仅考虑系统逻辑实现,可通过Log方式展现程序执行结果。
补充:
银行可能会出现vip的窗体正在办理一个vip用户的业务,而普通窗体此时空暇,那么再来一个vip用户(无论是什么用户),他应该是能够去普通窗体办理业务的#
我的核心处理逻辑就是,有一个WindowList,它里面持有者全部的Winodw(就是银行的服务窗体),它有getIdelVIPWindow,getIdelNormalWindow等方法,顾名思义,getIdelVIPWindow就是获取如今空暇的一个VIP窗体#(Window里面有一个字段是isBusy,是boolean型的)
有一个Produce,它负责依照1:6:3的比例产生各种客户,分别放到normals,vips,quicks等3个队列
Consumer就是一个个客户,它有execute方法#顾客去柜台办理业务的时候,所花的时间和柜台没有关系,仅仅和自己的业务相关#因此,execute里面会依据consumer的type来决定线程sleep多长时间
调度器就是dispatcher,它调用Produce不断生成客户,通过WindowList获得一个空暇的窗体,让这个窗体去"叫"自己相应的顾客#比如一个空暇的vip窗体,就会先去vip队列里找人,假设vip队列里面没有人,窗体就会去quick队列找人....
类图例如以下:
代码例如以下:
package bank; /** * This class is used for ... * @author dlf(460795365@qq.com) * @version 1.0, 2017年2月21日 下午10:10:46 */ public class Consumer { public Integer id; public String type; public Consumer(Integer id,String type){ this.id=id; this.type=type; } public void execute(){ try{ if (type.equals("normal")) { Thread.sleep(1000); return ; } if (type.equals("quick")) { Thread.sleep(300); return ; } if (type.equals("vip")) { Thread.sleep(1000); return ; } }catch(Exception exception){ exception.printStackTrace(); } } }
package bank; /** * This class is used for ... * * @author dlf(460795365@qq.com) * @version 1.0, 2017年2月21日 下午6:50:55 */ public abstract class Window { public int id; public String type; public Boolean isBusy; public void execute(Consumer client) { System.out.println(id + "号" + type + "业务员 開始办理" + client.id + "号" + client.type + "顾客的业务"); isBusy = true; client.execute(); isBusy = false; System.out.println(id + "号normal业务员 办理完了" + client.id + "号" + client.type + "顾客的业务"); } } class WindowForVIP extends Window { public WindowForVIP(int i) { id = i; type = "vip"; isBusy = false; } } class WindowForNormal extends Window { public WindowForNormal(int i) { id = i; type = "normal"; isBusy = false; } } class WindowForQuick extends Window { public WindowForQuick(int i) { id = i; type = "quick"; isBusy = false; } }
package bank; import java.util.ArrayList; import java.util.List; /** * This class is used for ... * @author dlf(460795365@qq.com) * @version 1.0, 2017年2月21日 下午7:55:34 */ public class WindowList { public List<WindowForNormal> normallist=new ArrayList<>(); public List<WindowForVIP> viplist=new ArrayList<>(); public List<WindowForQuick> quicklist=new ArrayList<>(); public WindowList(){ for(int i=1;i<5;i++) normallist.add(new WindowForNormal(i)); quicklist.add(new WindowForQuick(5)); viplist.add(new WindowForVIP(6)); } public Window getIdelVIPWindow(){ for(Window s:viplist){ if(!s.isBusy){ return s; } } return null; } public Window getIdelNormalWindow(){ for(Window s:normallist){ if(!s.isBusy){ return s; } } return null; } public Window getIdelQuickWindow(){ for(Window s:quicklist){ if(!s.isBusy){ return s; } } return null; } }
package bank; import java.util.Random; import java.util.concurrent.ArrayBlockingQueue; /** * This class is used for ... * @author dlf(460795365@qq.com) * @version 1.0, 2017年2月21日 下午7:01:18 */ public class Producer { //省略get/set方法 public ArrayBlockingQueue<Consumer> normals; public ArrayBlockingQueue<Consumer> vips; public ArrayBlockingQueue<Consumer> quicks; public void produce(){ Random random=new Random(); Random time=new Random(); int i=1; try { while (true) { //产生1-10 int type=random.nextInt(10)+1; if (type==1) { System.out.println("产生第"+i+"个客户,他是vip用户"); vips.put(new Consumer(i++, "vip")); }else if (type<5) { System.out.println("产生第"+i+"个客户,他是高速用户"); quicks.put(new Consumer(i++, "高速")); }else { System.out.println("产生第"+i+"个客户,他是普通用户"); normals.put(new Consumer(i++, "普通")); } Thread.sleep(time.nextInt(1000)); } } catch (Exception e) { // TODO: handle exception } } }
以下就是最核心的分发器,就是指派某个窗体处理某个顾客的逻辑
package bank; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * This class is used for ... * * @author dlf(460795365@qq.com) * @version 1.0, 2017年2月21日 下午7:14:18 */ public class Dispatcher { /** * @param threadPool * @param Windows * @param vips * @param normals * @param quicks */ public void doQuick(ExecutorService threadPool, WindowList Windows, ArrayBlockingQueue<Consumer> vips, ArrayBlockingQueue<Consumer> normals, ArrayBlockingQueue<Consumer> quicks) { try { while (true) { // do vip final Window window = Windows.getIdelQuickWindow(); if (window != null) { int flag = 0; final Consumer id_quick = quicks.poll(10, TimeUnit.MILLISECONDS); if (id_quick != null) // quick里面有人 run(window, id_quick, threadPool); flag = 1; if (flag == 0) { final Consumer id_vip = vips.poll(10, TimeUnit.MILLISECONDS); if (id_vip != null) // quick里面没人 vip队伍里有人排队 run(window, id_vip, threadPool); flag = 1; } if (flag == 0) { final Consumer id_normal = normals.poll(10, TimeUnit.MILLISECONDS); if (id_normal != null) { // quick也没有人 vip队伍里没人排队 normal 里面有人 run(window, id_normal, threadPool); } } } else { // vip窗体正在忙 Thread.sleep(1000); } } } catch (Exception e) { e.printStackTrace(); } } /** * @param id_quick * @param threadPool */ private static void run(final Window window, final Consumer consumer, ExecutorService threadPool) { threadPool.execute(new Runnable() { public void run() { window.execute(consumer); } }); } /** * @param threadPool * @param list * @param vips */ public void doNomal(ExecutorService threadPool, WindowList list, ArrayBlockingQueue<Consumer> vips, ArrayBlockingQueue<Consumer> normals, ArrayBlockingQueue<Consumer> quicks) { try { while (true) { // do vip final Window window = list.getIdelNormalWindow(); if (window != null) { int flag = 0; final Consumer id_normal = normals.poll(10, TimeUnit.MILLISECONDS); if (id_normal != null) // normal 里面有人 run(window, id_normal, threadPool); flag = 1; if (flag == 0) { final Consumer id_quick = quicks.poll(10, TimeUnit.MILLISECONDS); if (id_quick != null) // normal里面没人 quick里面有人 run(window, id_quick, threadPool); flag = 1; } if (flag == 0) { final Consumer id_vip = vips.poll(10, TimeUnit.MILLISECONDS); if (id_vip != null) // normal里面没人 normal里面没人 vip队伍里有人排队 run(window, id_vip, threadPool); flag = 1; } } else { // normal窗体正在忙 Thread.sleep(1000); } } } catch (Exception e) { e.printStackTrace(); } } /** * @param vips * @param list * @param threadPool * @param quicks * @param normals * */ public void doVIP(ExecutorService threadPool, WindowList list, ArrayBlockingQueue<Consumer> vips, ArrayBlockingQueue<Consumer> normals, ArrayBlockingQueue<Consumer> quicks) { try { while (true) { // do vip final Window window = list.getIdelVIPWindow(); if (window != null) { // vip窗体空暇 // System.out.println("vips is null?"+vips==null); final Consumer id_vip = vips.poll(10, TimeUnit.MILLISECONDS); int flag = 0; if (id_vip != null) { // vip队伍里有人排队 run(window, id_vip, threadPool); flag = 1; } if (flag == 0) { final Consumer id_quick = quicks.poll(10, TimeUnit.MILLISECONDS); if (id_quick != null) // vip队伍里没人排队 quick里面有人 run(window, id_quick, threadPool); flag = 1; } if (flag == 0) { final Consumer id_normal = normals.poll(10, TimeUnit.MILLISECONDS); if (id_normal != null) // vip队伍里没人排队 quick也里面有人 normal 里面有人 run(window, id_normal, threadPool); } } else { // vip窗体正在忙 Thread.sleep(1000); } } } catch (Exception e) { e.printStackTrace(); } } }
package bank; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; /** * This class is used for ... * @author dlf(460795365@qq.com) * @version 1.0, 2017年2月22日 下午5:22:01 */ public class Main { public static void main(String[] args) { final ExecutorService threadPool = Executors.newCachedThreadPool(); // 每一个队伍 最多有10人 final ArrayBlockingQueue<Consumer> normals = new ArrayBlockingQueue<>(10); final ArrayBlockingQueue<Consumer> vips = new ArrayBlockingQueue<>(10); final ArrayBlockingQueue<Consumer> quicks = new ArrayBlockingQueue<>(10); final WindowList Windows = new WindowList(); final Dispatcher dispatcher=new Dispatcher(); final Producer producer = new Producer(); producer.setNormals(normals); producer.setQuicks(quicks); producer.setVips(vips); threadPool.execute(new Runnable() { public void run() { producer.produce(); } }); threadPool.execute(new Runnable() { public void run() { dispatcher.doVIP(threadPool, Windows, vips, normals, quicks); } }); threadPool.execute(new Runnable() { public void run() { dispatcher.doQuick(threadPool, Windows, vips, normals, quicks); } }); threadPool.execute(new Runnable() { public void run() { dispatcher.doNomal(threadPool, Windows, vips, normals, quicks); } }); threadPool.execute(new Runnable() { public void run() { try { while (true) { // http://blog.csdn.net/yingzishizhe/article/details/8769907 int threadCount = ((ThreadPoolExecutor) threadPool).getActiveCount(); System.out.println("如今活跃的线程数量为: " + threadCount); System.out.println("如今排队的人数为:" + (vips.size() + normals.size() + quicks.size())); Thread.sleep(3000); } } catch (Exception e) { e.printStackTrace(); } } }); } } 最后的打印出来的信息例如以下:
产生第1个客户,他是高速用户 如今活跃的线程数量为: 5 如今排队的人数为:0 5号quick业务员 開始办理1号高速顾客的业务 5号normal业务员 办理完了1号高速顾客的业务 产生第2个客户,他是普通用户 1号normal业务员 開始办理2号普通顾客的业务 1号normal业务员 办理完了2号普通顾客的业务 产生第3个客户,他是高速用户 5号quick业务员 開始办理3号高速顾客的业务 5号normal业务员 办理完了3号高速顾客的业务 产生第4个客户,他是普通用户 1号normal业务员 開始办理4号普通顾客的业务 1号normal业务员 办理完了4号普通顾客的业务 产生第5个客户,他是高速用户 5号quick业务员 開始办理5号高速顾客的业务 5号normal业务员 办理完了5号高速顾客的业务 如今活跃的线程数量为: 5 如今排队的人数为:0 产生第6个客户,他是普通用户 1号normal业务员 開始办理6号普通顾客的业务 1号normal业务员 办理完了6号普通顾客的业务 产生第7个客户,他是高速用户 5号quick业务员 開始办理7号高速顾客的业务 5号normal业务员 办理完了7号高速顾客的业务 产生第8个客户,他是高速用户 5号quick业务员 開始办理8号高速顾客的业务 5号normal业务员 办理完了8号高速顾客的业务 产生第9个客户,他是普通用户 1号normal业务员 開始办理9号普通顾客的业务 1号normal业务员 办理完了9号普通顾客的业务 产生第10个客户,他是高速用户 5号quick业务员 開始办理10号高速顾客的业务 5号normal业务员 办理完了10号高速顾客的业务 产生第11个客户,他是普通用户 1号normal业务员 開始办理11号普通顾客的业务 1号normal业务员 办理完了11号普通顾客的业务 如今活跃的线程数量为: 5 如今排队的人数为:0 产生第12个客户,他是普通用户 1号normal业务员 開始办理12号普通顾客的业务 1号normal业务员 办理完了12号普通顾客的业务 产生第13个客户,他是高速用户 5号quick业务员 開始办理13号高速顾客的业务 5号normal业务员 办理完了13号高速顾客的业务 产生第14个客户,他是普通用户 1号normal业务员 開始办理14号普通顾客的业务 1号normal业务员 办理完了14号普通顾客的业务 产生第15个客户,他是普通用户 1号normal业务员 開始办理15号普通顾客的业务 1号normal业务员 办理完了15号普通顾客的业务 产生第16个客户,他是普通用户 1号normal业务员 開始办理16号普通顾客的业务 1号normal业务员 办理完了16号普通顾客的业务 如今活跃的线程数量为: 5 如今排队的人数为:0 产生第17个客户,他是高速用户 5号quick业务员 開始办理17号高速顾客的业务 5号normal业务员 办理完了17号高速顾客的业务 产生第18个客户,他是普通用户 1号normal业务员 開始办理18号普通顾客的业务 1号normal业务员 办理完了18号普通顾客的业务 产生第19个客户,他是普通用户 1号normal业务员 開始办理19号普通顾客的业务 1号normal业务员 办理完了19号普通顾客的业务 产生第20个客户,他是普通用户 1号normal业务员 開始办理20号普通顾客的业务 1号normal业务员 办理完了20号普通顾客的业务 产生第21个客户,他是高速用户 5号quick业务员 開始办理21号高速顾客的业务 5号normal业务员 办理完了21号高速顾客的业务 产生第22个客户,他是普通用户 1号normal业务员 開始办理22号普通顾客的业务 1号normal业务员 办理完了22号普通顾客的业务 如今活跃的线程数量为: 5 如今排队的人数为:0 产生第23个客户,他是普通用户 1号normal业务员 開始办理23号普通顾客的业务 1号normal业务员 办理完了23号普通顾客的业务 产生第24个客户,他是普通用户 1号normal业务员 開始办理24号普通顾客的业务 1号normal业务员 办理完了24号普通顾客的业务 产生第25个客户,他是普通用户 1号normal业务员 開始办理25号普通顾客的业务 1号normal业务员 办理完了25号普通顾客的业务 产生第26个客户,他是普通用户 1号normal业务员 開始办理26号普通顾客的业务 1号normal业务员 办理完了26号普通顾客的业务 产生第27个客户,他是高速用户 6号vip业务员 開始办理27号高速顾客的业务 6号normal业务员 办理完了27号高速顾客的业务 产生第28个客户,他是普通用户 1号normal业务员 開始办理28号普通顾客的业务 1号normal业务员 办理完了28号普通顾客的业务 如今活跃的线程数量为: 5 如今排队的人数为:0 产生第29个客户,他是普通用户 1号normal业务员 開始办理29号普通顾客的业务 1号normal业务员 办理完了29号普通顾客的业务 产生第30个客户,他是普通用户 1号normal业务员 開始办理30号普通顾客的业务 1号normal业务员 办理完了30号普通顾客的业务 产生第31个客户,他是普通用户 1号normal业务员 開始办理31号普通顾客的业务 1号normal业务员 办理完了31号普通顾客的业务 产生第32个客户,他是高速用户 5号quick业务员 開始办理32号高速顾客的业务 5号normal业务员 办理完了32号高速顾客的业务 产生第33个客户,他是普通用户 1号normal业务员 開始办理33号普通顾客的业务 1号normal业务员 办理完了33号普通顾客的业务 如今活跃的线程数量为: 5 如今排队的人数为:0 产生第34个客户,他是高速用户 6号vip业务员 開始办理34号高速顾客的业务 6号normal业务员 办理完了34号高速顾客的业务 产生第35个客户,他是普通用户 1号normal业务员 開始办理35号普通顾客的业务 1号normal业务员 办理完了35号普通顾客的业务 产生第36个客户,他是普通用户 1号normal业务员 開始办理36号普通顾客的业务 1号normal业务员 办理完了36号普通顾客的业务 产生第37个客户,他是普通用户 1号normal业务员 開始办理37号普通顾客的业务 1号normal业务员 办理完了37号普通顾客的业务 如今活跃的线程数量为: 5 如今排队的人数为:0 产生第38个客户,他是普通用户 1号normal业务员 開始办理38号普通顾客的业务 1号normal业务员 办理完了38号普通顾客的业务 产生第39个客户,他是高速用户 5号quick业务员 開始办理39号高速顾客的业务 5号normal业务员 办理完了39号高速顾客的业务 产生第40个客户,他是vip用户 6号vip业务员 開始办理40号vip顾客的业务 产生第41个客户,他是普通用户 1号normal业务员 開始办理41号普通顾客的业务 1号normal业务员 办理完了41号普通顾客的业务 6号normal业务员 办理完了40号vip顾客的业务 如今活跃的线程数量为: 5 如今排队的人数为:0