---------------------- android培训、java培训、期待与您交流! ----------------------
需求
1.银行内有6个业务窗口,1-4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。
2.有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。
3.异步随机生成各种类型的客户,生成各类型用户的概率比例为 VIP客户:普通客户:快速客户 = 1:6:3。
4.客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需的时间,快速客户办理业务所需时间为最小值(提示:办理业务的过程可通过线程Sleep的方式模拟)。
5.各类型客户在其对应窗口按顺序依次办理业务。
面向对象的分析与设计
1.号码管理器:这个对象不断的产生三种类型号码,就等于随机生成三种类型的客户。
2.一个号码机器,统一管理三个号码管理器。
3.对应类型的窗口依次叫号
三种服务和客户类别---枚举
package cn.itcast.bank; public enum CustomerType { COMMON,EXPRESS,VIP; public String toString(){ switch(this){ case COMMON: return "普通"; case EXPRESS: return "快速"; case VIP: return "VIP"; } return null; } }
用于定义服务时间的类
package cn.itcast.bank; public class Constants { public static int MAX_SERVICE_TIME = 10000; public static int MIN_SERVICE_TIME = 1000; public static int COMMON_CUSTOMER_INTERVAL_TIME = 1; }
取号机和号码生成器
客户通过取号机取号,取号机调用号码生成器的generateNumber()方法取号,号码生成器把客户取的号存入对应客户类型的号码排队队列。
对应的窗口调用取号机的fetchServiceNumber()从对应的号码排队队列中取出第一个号码,进行叫号服务。
注意: static NumberMachine instance = new NumberMachine() 此处用static修饰,以便同一种类型的客户,使用的是一个排队队列。
package cn.itcast.bank; 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 fetchServiceNumber(){ Integer number = null; if(queueNumber.size()>0){ number = queueNumber.remove(0); } return number; } }
package cn.itcast.bank; public class NumberMachine { private NumberManager commonManager = new NumberManager(); private NumberManager expressManger = new NumberManager(); private NumberManager vipManager = new NumberManager(); public NumberManager getCommonManager() { return commonManager; } public void setCommonManager(NumberManager commonManager) { this.commonManager = commonManager; } public NumberManager getExpressManger() { return expressManger; } public void setExpressManger(NumberManager expressManger) { this.expressManger = expressManger; } public NumberManager getVipManager() { return vipManager; } public void setVipManager(NumberManager vipManager) { this.vipManager = vipManager; } private NumberMachine(){} public static NumberMachine getInstance(){ return instance; } private static NumberMachine instance = new NumberMachine(); }
6个服务窗口
服务窗分为:普通窗口、快速窗口、vip窗口、
普通窗口:普通窗口开启后循环从普通客户排队队列中取出第一个客户进行服务。
快速窗口:快速窗口开启后循环从快速客户排队队列中取出第一个客户进行服务,若无快速客户,从普通客户排队队列中取出第一个普通客户进行服务。
vip窗口:vip窗口开启后循环从vip客户排队队列中取出第一个客户进行服务,若无vip客户,从普通客户排队队列中取出第一个普通客户进行服务。
package cn.itcast.bank; import java.util.Random; import java.util.concurrent.Executors; public class ServiceWindow { private CustomerType type = CustomerType.COMMON; private int windowId = 1; public void setWindowId(int windowId) { this.windowId = windowId; } public void setType(CustomerType type) { this.type = type; } //开始服务 public void start() { Executors.newSingleThreadExecutor().execute(new Runnable() { public void run() { while (true) { switch (type) { case COMMON: commonService(); break; case EXPRESS: expressService(); break; case VIP: vipService(); break; } } } }); } //普通窗口开始叫普通客户 private void commonService() { String windowName = "第" + windowId + "号" + type + "窗口"; System.out.println(windowName + "正在获取任务"); Integer number = NumberMachine.getInstance().getCommonManager() .fetchServiceNumber(); if (number != null) { long beginTime = System.currentTimeMillis(); int maxRand = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME; long serveTime = new Random().nextInt(maxRand) + 1 + Constants.MIN_SERVICE_TIME; System.out.println(windowName + "正在为第" + number + "个" + type + "客户服务==============="); try { Thread.sleep(serveTime); } catch (InterruptedException e) { e.printStackTrace(); } long endTime = System.currentTimeMillis(); System.out.println(windowName + "为第" + number + "个" + type + "客户完成服务,耗时" + (endTime - beginTime) / 1000 + "s"); } else { System.out.println(windowName + "没有取到任务,先休息1秒钟!"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } //快速窗口开始叫快速客户的号,若无快速客户,叫普通客户。 private void expressService() { String windowName = "第" + windowId + "号快速窗口"; System.out.println(windowName + "正在获取任务"); Integer number = NumberMachine.getInstance().getExpressManger() .fetchServiceNumber(); if (number != null) { long beginTime = System.currentTimeMillis(); long serveTime = Constants.MIN_SERVICE_TIME; System.out.println(windowName + "正在为第" + number + "个" + type + "客户服务==============="); try { Thread.sleep(serveTime); } catch (InterruptedException e) { e.printStackTrace(); } long endTime = System.currentTimeMillis(); System.out.println(windowName + "为第" + number + "个" + type + "客户完成服务,耗时" + (endTime - beginTime) / 1000 + "s"); } else { commonService(); } } //vip窗口开始叫vip客户的号,若无vip客户,叫普通客户。 private void vipService() { String windowName = "第" + windowId + "号VIP窗口"; System.out.println(windowName + "正在获取任务"); Integer number = NumberMachine.getInstance().getVipManager() .fetchServiceNumber(); if (number != null) { long beginTime = System.currentTimeMillis(); int maxRand = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME; long serveTime = new Random().nextInt(maxRand) + 1 + Constants.MIN_SERVICE_TIME; System.out.println(windowName + "正在为第" + number + "个" + type + "客户服务==============="); try { Thread.sleep(serveTime); } catch (InterruptedException e) { e.printStackTrace(); } long endTime = System.currentTimeMillis(); System.out.println(windowName + "为第" + number + "个" + type + "客户完成服务,耗时" + (endTime - beginTime) / 1000 + "s"); } else { System.out.println(windowName + "没有取到任务,先休息1秒钟!"); commonService(); } } }
主调度类
主调度类启动后:
1.开启6个服务窗口(6个服务线程),按各自窗口的服务规则,开始循环检索客户排队队列,开始服务。
2.启动三个定时器,按各自的频率生成模拟客户,进行取号排队。以至系统自动运作。
package cn.itcast.bank; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class MainClass { public static void main(String[] args) { // 开启4个普通服务窗口 ServiceWindow commonwindow = null; for (int i = 1; i < 5; i++) { commonwindow = new ServiceWindow(); commonwindow.setWindowId(i); commonwindow.setType(CustomerType.COMMON); commonwindow.start(); } // 开启一个快速服务窗口 ServiceWindow expressWindow = new ServiceWindow(); commonwindow.setWindowId(5); expressWindow.setType(CustomerType.EXPRESS); expressWindow.start(); // 开启一个vip服务窗口 ServiceWindow vipWindow = new ServiceWindow(); commonwindow.setWindowId(6); vipWindow.setType(CustomerType.VIP); vipWindow.start(); // 普通客户取号 Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() { public void run() { Integer number = NumberMachine.getInstance().getCommonManager() .generateNumber(); System.out.println(number + "号普通客户等待服务"); } }, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME * 1, TimeUnit.SECONDS); // 快速客户取号 Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() { public void run() { Integer number = NumberMachine.getInstance().getExpressManger() .generateNumber(); System.out.println(number + "号快速客户等待服务"); } }, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME * 2, TimeUnit.SECONDS); // vip客户取号 Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() { public void run() { Integer number = NumberMachine.getInstance().getVipManager() .generateNumber(); System.out.println(number + "号vip客户等待服务"); } }, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME * 3, TimeUnit.SECONDS); } }
感觉这是学程序以来,见过的最经典的程序,把多线程用的如此到位,可能是自己本来就没什么见识吧,这个系统的设计思想,基本上同交通管理系统如出一辙,都是同样设计思想,要多摸索一下,以便熟练掌握这种设计思想。
---------------------- android培训、java培训、期待与您交流! ----------------------详细请查看:http://edu.csdn.net/heima