黑马程序员—银行调度系统解析
来源:互联网 发布:美工发展方向 编辑:程序博客网 时间:2024/06/03 14:51
-------------
模拟实现银行业务调度系统逻辑,具体需求如下:
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
以下是我自己的理解(非张老师的正解,有错误):
* 1,return commonList.remove(0);提示这里出现越界异常
* 2,打印中出现缺少对某个号客户的处理情况,其中一次缺少 7号xx用户
* 3,打印结果中出现了客户编号的重复:[1号普通客户][1号快速客户]
import java.util.ArrayList;import java.util.List;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;import java.util.Random;public class Test {public static void main(String[] args) {// 定时生成三种不同类型的客户comeClient(Client.COMMON_CLIENT, 1);comeClient(Client.RAPID_CLIENT, 2);comeClient(Client.VIP_CLIENT, 6);try {Thread.sleep(5000);} catch (Exception e) {}// 先让程序休息5秒,聚集一些客户// 以下建立7个银行窗口,进行死循环,并让每个窗口都不停的叫号Executors.newSingleThreadExecutor().execute(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubwhile (true)new BankWindows().getNum();}});Executors.newSingleThreadExecutor().execute(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubwhile (true)new BankWindows("common", 5).getNum();}});Executors.newSingleThreadExecutor().execute(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubwhile (true)new BankWindows("common", 2).getNum();}});Executors.newSingleThreadExecutor().execute(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubwhile (true)new BankWindows("rapid", 6).getNum();}});Executors.newSingleThreadExecutor().execute(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubwhile (true)new BankWindows("common", 3).getNum();}});Executors.newSingleThreadExecutor().execute(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubwhile (true)new BankWindows("common", 4).getNum();}});Executors.newSingleThreadExecutor().execute(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubwhile (true)new BankWindows("vip", 7).getNum();}});}public static void comeClient(final Client client, int intervalTime) {Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubnew SortNum().start(client);}}, 0, intervalTime, TimeUnit.SECONDS);}}
// 这个类定义了三种不同客户原型enum Client {COMMON_CLIENT, RAPID_CLIENT, VIP_CLIENT;@Overridepublic String toString() {// TODO Auto-generated method stubswitch (this) {case COMMON_CLIENT:return "普通客户";case RAPID_CLIENT:return "快速客户";case VIP_CLIENT:return "VIP客户";}return super.toString();}}
//实现客户排号能class SortNum {// 三个list用于记录三种客户private static List commonList = new ArrayList();private static List rapidList = new ArrayList();private static List vipList = new ArrayList();// 对应三种客户的取出队列最前的客户的方法,用了synchronized修饰,但还会出现// 线程安全问题,这三个函数偶尔出现越界异常public synchronized String getCommonListNum() {if (commonList.size() > 0 && commonList != null)return commonList.remove(0);elsereturn "没有客户";}public synchronized String getRapidListNum() {if (rapidList.size() > 0 && rapidList != null)return rapidList.remove(0);elsereturn "没有客户";}public synchronized String getVipListNum() {if (vipList.size() > 0 && vipList != null)return vipList.remove(0);elsereturn "没有客户";}static int count = 0;// 定义计数器public synchronized void start(Client client) {int n = ++count;switch (client) {case COMMON_CLIENT:commonList.add("第" + n + "号普通客户");System.out.println(commonList.toString());break;case RAPID_CLIENT:rapidList.add("第" + n + "号快速客户");System.out.println(rapidList.toString());break;case VIP_CLIENT:vipList.add("第" + n + "号VIP客户");System.out.println(vipList.toString());break;}}}
//建立银行窗口类class BankWindows {private String str = "common";private int count = 1;public BankWindows() {// TODO Auto-generated constructor stub}public BankWindows(String flag, int count) {this.str = flag;this.count = count;}public void getNum() {SortNum sortNum = new SortNum();if (str.equals("common")) {String client = sortNum.getCommonListNum();while (client.equals("没有客户")) {System.out.println(count + "号普通窗口休息中...");try {Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}client = sortNum.getCommonListNum();}System.out.println(client + "正在" + count + "号普通窗口办理业务");int m = (new Random().nextInt(9) + 1) * 1000;try {Thread.sleep(m);} catch (Exception e) {e.printStackTrace();}System.out.println(client + "业务办理完毕,用时" + (m / 1000) + "s");}if (str.equals("rapid")) {// 此处出现问题,导致丢元素String client = sortNum.getRapidListNum();String client2 = sortNum.getCommonListNum();while (client.equals("没有客户")) {if (client2.equals("没有客户")) {System.out.println(count + "号快速窗口休息中...");try {Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}// continue;} else {System.out.println(client2 + "正在" + count + "号快速窗口办理业务");int m = (new Random().nextInt(9) + 1) * 1000;try {Thread.sleep(m);} catch (Exception e) {e.printStackTrace();}System.out.println(client2 + "业务办理完毕,用时" + (m / 1000) + "s");}client = sortNum.getRapidListNum();}System.out.println(client + "正在" + count + "号快速窗口办理业务");try {Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}System.out.println(client + "业务办理完毕,用时1s");}if (str.equals("vip")) {String client = sortNum.getVipListNum();String client2 = sortNum.getCommonListNum();while (client.equals("没有客户")) {if (client2.equals("没有客户")) {System.out.println(count + "号VIP窗口休息中...");try {Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}// continue;} else {System.out.println(client2 + "正在" + count + "号VIP窗口办理业务");int m = (new Random().nextInt(9) + 1) * 1000;try {Thread.sleep(m);} catch (Exception e) {e.printStackTrace();}System.out.println(client2 + "业务办理完毕,用时" + (m / 1000) + "s");}client = sortNum.getVipListNum();}System.out.println(client + "正在" + count + "号VIP窗口办理业务");int m = (new Random().nextInt(9) + 1) * 1000;try {Thread.sleep(m);} catch (Exception e) {e.printStackTrace();}System.out.println(client + "业务办理完毕,用时" + (m / 1000) + "s");}}}
-------------------------------------------------------------------------------
张老师的讲解:
首先:面向对象的分析与设计
l
Ø
Ø
l
Ø
如果我不是多次亲身经历银行的这种业务,再加之积累了大量面向对象的应用开发经验,我也不知道能否轻松进行这种设计,能否发掘出其中隐含的对象信息,我真说不出具体的经验是什么,就是日积月累出来的一种感觉。难道这就是传说中的:“只可意会,不可言传?”
类图表示:
²
Ø
Ø
代码示例:
package cn.itcast.bankqueue;import java.util.ArrayList;import java.util.List;public class NumberManager {private int lastNumber = 0;private List queueNumbers = new ArrayList();public synchronized Integer generateNewNumber(){ queueNumbers.add(++lastNumber); return lastNumber;}public synchronized Integer fetchNumber(){ if(queueNumbers.size()>0){ return (Integer)queueNumbers.remove(0); }else{ return null; } }}
²
Ø
代码示例:
package cn.itcast.bankqueue; public class NumberMachine { private NumberMachine(){}private static NumberMachine instance = new NumberMachine();public static NumberMachine getInstance(){ return instance;} private NumberManager commonManager = new NumberManager();private NumberManager expressManager = new NumberManager();private NumberManager vipManager = new NumberManager();public NumberManager getCommonManager() { return commonManager;}public NumberManager getExpressManager() { return expressManager;}public NumberManager getVipManager() { return vipManager; }}
²
Ø
Ø
代码示例:
package cn.itcast.bankqueue;public enum CustomerType {COMMON,EXPRESS,VIP;public String toString(){ String name = null; switch(this){ case COMMON: name = "普通"; break; case EXPRESS: name = "快速"; break; case VIP: name = name(); break; } return name; }}
²
Ø
Ø
代码示例:
package cn.itcast.bankqueue;import java.util.Random;import java.util.concurrent.Executors;import java.util.logging.Logger;public class ServiceWindow { private static Logger logger = Logger.getLogger("cn.itcast.bankqueue"); private CustomerType type = CustomerType.COMMON; private int number = 1; public CustomerType getType() { return type; } public void setType(CustomerType type) { this.type = type; } public void setNumber(int number){ this.number = number; } public void start(){ Executors.newSingleThreadExecutor().execute( new Runnable(){ public void run(){ //下面这种写法的运行效率低,最好是把while放在case下面 while(true){ switch(type){ case COMMON: commonService(); break; case EXPRESS: expressService(); break; case VIP: vipService(); break; } } } } ); } private void commonService(){ String windowName = "第" + number + "号" + type + "窗口"; System.out.println(windowName + "开始获取普通任务!"); Integer serviceNumber = NumberMachine.getInstance().getCommonManager().fetchNumber(); if(serviceNumber != null ){ System.out.println(windowName + "开始为第" + serviceNumber + "号普通客户服务"); int maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME; int serviceTime = new Random().nextInt(maxRandom)+1 + Constants.MIN_SERVICE_TIME; try { Thread.sleep(serviceTime); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(windowName + "完成为第" + serviceNumber + "号普通客户服务,总共耗时" + serviceTime/1000 + "秒"); }else{ System.out.println(windowName + "没有取到普通任务,正在空闲一秒"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } private void expressService(){ Integer serviceNumber = NumberMachine.getInstance().getExpressManager().fetchNumber(); String windowName = "第" + number + "号" + type + "窗口"; System.out.println(windowName + "开始获取快速任务!"); if(serviceNumber !=null){ System.out.println(windowName + "开始为第" + serviceNumber + "号快速客户服务"); int serviceTime = Constants.MIN_SERVICE_TIME; try { Thread.sleep(serviceTime); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(windowName + "完成为第" + serviceNumber + "号快速客户服务,总共耗时" + serviceTime/1000 + "秒"); }else{ System.out.println(windowName + "没有取到快速任务!"); commonService(); } } private void vipService(){ Integer serviceNumber = NumberMachine.getInstance().getVipManager().fetchNumber(); String windowName = "第" + number + "号" + type + "窗口"; System.out.println(windowName + "开始获取VIP任务!"); if(serviceNumber !=null){ System.out.println(windowName + "开始为第" + serviceNumber + "号VIP客户服务"); int maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME; int serviceTime = new Random().nextInt(maxRandom)+1 + Constants.MIN_SERVICE_TIME; try { Thread.sleep(serviceTime); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(windowName + "完成为第" + serviceNumber + "号VIP客户服务,总共耗时" + serviceTime/1000 + "秒"); }else{ System.out.println(windowName + "没有取到VIP任务!"); commonService(); } }}
²
Ø
Ø
代码示例:
package cn.itcast.bankqueue; import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;import java.util.logging.Logger; public class MainClass { private static Logger logger = Logger.getLogger("cn.itcast.bankqueue"); public static void main(String[] args) { //产生4个普通窗口 for(int i=1;i<5;i++){ ServiceWindow window = new ServiceWindow(); window.setNumber(i); window.start(); } //产生1个快速窗口 ServiceWindow expressWindow = new ServiceWindow(); expressWindow.setType(CustomerType.EXPRESS); expressWindow.start(); //产生1个VIP窗口 ServiceWindow vipWindow = new ServiceWindow(); vipWindow.setType(CustomerType.VIP); vipWindow.start(); //普通客户拿号 Executors.newScheduledThreadPool(1).scheduleAtFixedRate( new Runnable(){ public void run(){ Integer serviceNumber = NumberMachine.getInstance().getCommonManager().generateNewNumber(); //logger.info("第" + serviceNumber + "号普通客户正在等待服务!"); System.out.println("第" + serviceNumber + "号普通客户正在等待服务!"); } }, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME, TimeUnit.SECONDS); //快速客户拿号 Executors.newScheduledThreadPool(1).scheduleAtFixedRate( new Runnable(){ public void run(){ Integer serviceNumber = NumberMachine.getInstance().getExpressManager().generateNewNumber(); System.out.println("第" + serviceNumber + "号快速客户正在等待服务!"); } }, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME * 2, TimeUnit.SECONDS); //VIP客户拿号 Executors.newScheduledThreadPool(1).scheduleAtFixedRate( new Runnable(){ public void run(){ Integer serviceNumber = NumberMachine.getInstance().getVipManager().generateNewNumber(); System.out.println("第" + serviceNumber + "号VIP客户正在等待服务!"); } }, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME * 6, TimeUnit.SECONDS); }}
Ø
代码示例:
package cn.itcast.bankqueue;public class Constants {public static int MAX_SERVICE_TIME = 10000; //10秒!public static int MIN_SERVICE_TIME = 1000; //1秒!public static int COMMON_CUSTOMER_INTERVAL_TIME = 1; }
问题1:使用单例设计模式解决,防止创建多个SortNum类的对象出现的安全问题
问题2:BankWindows类中
问题3: 经过以上更改后,问题3没有再出现。
- 黑马程序员—银行调度系统解析
- 黑马程序员——银行调度系统
- 黑马程序员——银行调度系统
- 黑马程序员——银行调度系统
- 黑马程序员——银行调度系统
- 黑马程序员——银行调度系统
- 黑马程序员——银行调度系统
- 黑马程序员——银行调度系统
- 黑马程序员——银行调度系统
- 黑马程序员——银行调度系统
- 黑马程序员——银行调度系统
- 黑马程序员—银行调度系统
- 黑马程序员 银行调度系统
- 黑马程序员-银行调度系统
- 黑马程序员--银行调度系统
- 黑马程序员--银行调度系统
- 黑马程序员:银行调度系统
- 黑马程序员-银行调度系统
- A. Theatre Square
- 黑马程序员—交通灯管理系统解析
- Extjs gridPanel 选中的行创建右键菜单
- leetcode First Missing Positive
- 漫谈C语言及如何学习C语言
- 黑马程序员—银行调度系统解析
- NYOJ 592 spiral grid
- 基于android2.3.5系统:explicit关键字应用方法详解
- Java关键字: protected
- android mimeType 表
- Dependencies of Applications【每日一译】--2013-1-17
- java中抽象类和接口的区别?
- 陈妍希
- explicit使用注意事项