黑马程序员:银行业务调度系统分析及代码实现

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------银行业务调度系统
对象分析:
1.客户
2.服务窗口
3.号码机器


对象上的属性和方法分析:
客户
客户类型:普通客户、快速客户、VIP客户
需要用到枚举:因为客户类型是固定的三类客户


服务窗口
窗口类型:普通窗口、快速窗口、VIP窗口
功能:
1.提供设置窗口号、窗口类型的方法
2.获取号码并处理客户业务
需要用到多线程:因为是多个窗口同时工作的


号码机器
号码:普通号码、快速号码、VIP号码
功能:产生号码提供给客户、将产生的最前面的号码提供给窗口
需要用到同步:因为两个方法是不同线程操作,当多个线程操作同一个数据的时候会出现问题,所以要让他们互斥。
需要用到单例:因为号码机器只有一台


CustomerType:客户类型
/*
 * 因为客户类型是固定的三种类型,所以使用枚举
 * 判断当前枚举类型,并覆盖toString方法,根据枚举类型指定对应的客户类型name
 */
package cn.itcast.Mr_Zhang.BankQueue;


public enum CustomerType {
	COMMON,EXPRESS,VIP;
	
	public String toString(){
		String name = null;
		switch(this){
		case COMMON :
			name = "普通客户";
			return name;
		case EXPRESS :
			name = "快速客户";
			return name;
		case VIP :
			name = "VIP客户";
			return name;
		}
		return null;
	}
}


ServiceWindows:服务窗口
/*
 * 服务窗口共有三类:普通,快速,VIP
 * 1.若快速、VIP窗口没有未用户办理业务的时候,需要为普通客户办理业务
 * 2.VIP客户:普通客户:快速客户 = 1:6:3
 * 思路:
 * 1.窗口应该有对应的窗口ID、窗口名称、窗口类型
 * 2.根据客户类型选择对应窗口的业务执行方法
 * 3.窗口需要有工作的方法:即取号,并以Sleep代替办理业务的时间
 * 4.当快速和VIP窗口没有对应的快速和VIP客户时,需调用普通窗口的方法为普通客户服务
 */
package cn.itcast.Mr_Zhang.BankQueue;


import java.util.Random;
import java.util.concurrent.Executors;


public class ServiceWindows {
	/*初始化窗口号及客户类型并提供外部设置的方法*/
	private int windowId = 1;
	private CustomerType type = CustomerType.COMMON;
	
	public void setWindowId(int windowId) {
		this.windowId = windowId;
	}


	public void setType(CustomerType type) {
		this.type = type;
	}


	/*定义窗口启动方法,根据不同客户类型启动不同窗口
	 *这里要注意:若start中没用定义新线程来执行方法,那么在main方法中创建多个窗口的时候,第一个窗口被启动时就会一直循环。
	 *这里是完成整个项目犯错的地方,特别要注意
	 */
	public void start(){
		Executors.newSingleThreadExecutor().execute(new Runnable(){
			public void run(){
					switch(type){
					case COMMON :
						/*因为窗口启动之后需要一直处理该类型的客户,所以要一直使用该窗口的方法*/
						while(true)	
							commonWindow();
					case EXPRESS :
						while(true)	
							expressWindow();
					case VIP :
						while(true)	
							vipWindow();
					}
			}
		});
	
	
	}
	
	/*普通窗口*/
	private void commonWindow() {
		String windowName = "第" + windowId + "号" + type + "窗口";
		Integer number = NumberMechine.getNumberMechine().getCommonNumber().fetchNumber();
		System.out.println(windowName + "正在获取任务");
		if (number != null)
			try {
				int maxRondom = Constants.SERVICE_TIME_MAX - Constants.SERVICE_TIME_MIN;
				int serviceTime = new Random().nextInt(maxRondom) + 1 + Constants.SERVICE_TIME_MIN;
				Thread.sleep(serviceTime);
				System.out.println(windowName + "为第" + number + "号" + "普通客户服务,耗时:" + serviceTime/1000 + "秒");
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		else
			System.out.println(windowName + "没有获取到任务,等待一秒钟");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		
	}


	/*快速窗口*/
	private void expressWindow() {
		String windowName = "第" + windowId + "号" + type + "窗口";
		Integer number = NumberMechine.getNumberMechine().getExpressNumber().fetchNumber();
		if (number != null)
			try {
				int serviceTime = Constants.SERVICE_TIME_MIN;
				Thread.sleep(serviceTime);
				System.out.println(windowName + "为第" + number + "号" + "快速客户服务,耗时:" + serviceTime/1000 + "秒");
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		else 
			System.out.println(windowName + "未获取到任务,进入普通任务获取阶段");
			commonWindow();
	}
	
	/*VIP窗口*/
	private void vipWindow() {
		String windowName = "第" + windowId + "号" + type + "窗口";
		Integer number = NumberMechine.getNumberMechine().getVipNumber().fetchNumber();
		if (number != null)
			try {
				int maxRondom = Constants.SERVICE_TIME_MAX - Constants.SERVICE_TIME_MIN;
				int serviceTime = new Random().nextInt(maxRondom) + 1 + Constants.SERVICE_TIME_MIN;
				Thread.sleep(serviceTime);
				System.out.println(windowName + "为第" + number + "号" + "VIP客户服务,耗时:" + serviceTime/1000 + "秒");
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		else 
			System.out.println(windowName + "未获取到任务,进入普通任务获取阶段");
			/*若VIP窗口未取得VIP号码管理中的号码,则为普通客户服务*/
			commonWindow();
	}
}

NumberManager:号码管理器
/*
 * 号码管理器的功能:
 * 用户取号:产生号码
 * 窗口取号:取得已产生号码的最前面的号码
 */
package cn.itcast.Mr_Zhang.BankQueue;


import java.util.ArrayList;
import java.util.List;


public class NumberManager {
	private Integer lastNumber = 1;
	private List<Integer> queueNumber = new ArrayList<Integer>();


	/*
	 * 产生一个号码,代表一个用户取号 因为产生号码和获取号码是不同线程对同一个数据进行操作,这样会产生问题,必须让他们互斥,所以加入同步
	 */
	public synchronized Integer generateNumber() {
		queueNumber.add(lastNumber);
		return lastNumber++;
	}


	/* 窗口取得一个号码,代表依次为客户服务 */
	public synchronized Integer fetchNumber() {
		Integer number = null;
		if (queueNumber.size() > 0)
			number = queueNumber.remove(0);
		return number;
	}
}

NumberMechine:号码机器
/*
 * 1.整个系统中,取号机器只有一台,所以要设计成单例模式
 * 2.该类中应该提供通过反问该类对象返回三个数字管理器对象的方法
 */
package cn.itcast.Mr_Zhang.BankQueue;


public class NumberMechine {
	
	/*构造函数私有化,禁止外部创建对象*/
	private NumberMechine(){
		
	}
	
	/*为外部提供一个访问本类对象的方法*/
	private static final NumberMechine instance = new NumberMechine();
	public static NumberMechine getNumberMechine(){
		return instance;
	}
	
	/*创建普通、快速、VIP数字管理器对象并提供外部访问方法*/
	private NumberManager commonNumber = new NumberManager();
	private NumberManager expressNumber = new NumberManager();
	private NumberManager VipNumber = new NumberManager();
	
	public NumberManager getCommonNumber() {
		return commonNumber;
	}
	public NumberManager getExpressNumber() {
		return expressNumber;
	}
	public NumberManager getVipNumber() {
		return VipNumber;
	}
	
}

Constants:常量
package cn.itcast.Mr_Zhang.BankQueue;


public class Constants {
	public static final int SERVICE_TIME_MIN = 1000;
	public static final int SERVICE_TIME_MAX = 10000;
	public static final int COMMON_CUSTOMER_INTERVAL_TIME = 1;
}

mainClass:模拟运行系统


package cn.itcast.Mr_Zhang.BankQueue;


import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;


public class mainClass {
	public static void main(String[] args) {
		
		/*生成4个普通窗口并开启*/
		for(int i = 1; i<=4; i++){
			ServiceWindows commonWindow = new ServiceWindows();
			commonWindow.setType(CustomerType.COMMON);
			commonWindow.setWindowId(i);
			commonWindow.start();
		}


		/*生成1个快速窗口并开启*/
		ServiceWindows expressWindow = new ServiceWindows();
		expressWindow.setType(CustomerType.EXPRESS);
		expressWindow.start();
		
		/*生成1个VIP窗口并开启*/
		ServiceWindows vipWindow = new ServiceWindows();
		vipWindow.setType(CustomerType.VIP);
		vipWindow.start();
		
		
		/*按频率增加普通客户*/
		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
				new Runnable(){
					public void run(){
						Integer serviceNumber = NumberMechine.getNumberMechine().getCommonNumber().generateNumber();
						System.out.println("第" + serviceNumber + "号普通客户正在等待服务");
					}
				}, 
				0, 
				Constants.COMMON_CUSTOMER_INTERVAL_TIME, 
				TimeUnit.SECONDS);
		
		/*按频率增加快速客户*/
		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
				new Runnable(){
					public void run(){
						Integer serviceNumber = NumberMechine.getNumberMechine().getExpressNumber().generateNumber();
						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 = NumberMechine.getNumberMechine().getVipNumber().generateNumber();
						System.out.println("第" + serviceNumber + "号VIP客户正在等待服务");
					}
				}, 
				0, 
				Constants.COMMON_CUSTOMER_INTERVAL_TIME * 6, 
				TimeUnit.SECONDS);
	}
}

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------详细请查看: http://edu.csdn.net
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值