黑马程序员——java基础学习(银行业务调度系统)

---------------------- ASP.Net+Android+IOS开发</a>、.Net培训、期待与您交流! ----------------------

需求:

     银行内有6个业务窗口,1- 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。

     有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。

     异步随机生成各种类型的客户,生成各类型用户的概率比例为:

          VIP客户 :普通客户 :快速客户 =  1 :6 :3。

     客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需的时间,快速客户办理业务所需时间为最小值(提示:办理业务的过程可通过线程Sleep的方式模拟)。

      各类型客户在其对应窗口按顺序依次办理业务。

      当VIP(6号)窗口和快速业务(5号)窗口没有客户等待办理业务的时候,这两个窗口可以处理普通客户的业务,而一旦有对应的客户等待办理业务的时候,则优先处理对应客户的业务。

      随机生成客户时间间隔以及业务办理时间最大值和最小值自定,可以设置。

     不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。

分析:

     客户类型(ServerNumberQueue)将客户类型看成是要服务的号。固定为三种类型(VIP客户 、普通客户、快速客户),可通过枚举实现。里面用List存储当前等待服务的对象。

          因为因为三个窗口可能会同时操作普通客户,所以要注意数据的正确性。用同步代码块来保证。

     客户类型机器(ServerNumberMachine)用于自动三种类型的客户服务号。

     服务窗口(ServiceWindow)服务客户。有三种类型窗口。

各个类的实现:

     客户类型(ServerNumberQueue)

public enum ServerNumberQueue {
	VIP, COMMON, FAST;
	private List<String> numberQueue;//存储当前等待服务的客户号码队列
	private int currentNumber;		//记录当前客户号

	private ServerNumberQueue() {
		this.numberQueue = new LinkedList<String>();
		//建立客户对象时,让客户号从一个4000-4999的随机数开始
		this.currentNumber = new Random().nextInt(1000) + 4000;
	}

	public synchronized void setCurrentNumber(int num) {
		if (this.numberQueue.size() == 0) {
			this.currentNumber = num;
		}
	}
	/*
	 * 当服务窗口为一个对象服务完毕,调用该方法将服务号从队列中移除
	 *   可能多个服务窗口会同时服务,要加同步代码块
	 */
	public synchronized String fetchNumber() {
		if (this.numberQueue.size() > 0) {
			return this.numberQueue.remove(0);
		}
		return null;
	}
	/*
	 * 当客户管理器产生了一个客户时,将其添加到队列中
	 */
	public synchronized String generateNumber() {
		this.numberQueue.add(this.name() + " customer " + currentNumber++);
		//System.err.println(this.numberQueue);
		return this.numberQueue.get((this.numberQueue.size() - 1));
	}

	public synchronized int getQueueCount() {
		return this.numberQueue.size();
	}
}

     客户类型机器(ServerNumberMachine)
public class ServerNumberMachine {
	//程序运行时,只有一个客户型管理的机器,单例。
	private static ServerNumberMachine instance;
	/*
	 * 单例实现:构造方法私有,通过一个静态方法返回对象。
	 */
	private ServerNumberMachine(){}
	public static ServerNumberMachine getInstance(){
		if(instance == null){
			synchronized(ServerNumberMachine.class){
				if(instance == null){
					instance = new ServerNumberMachine();
				}
			}
		}
		return instance;
	}
	/*
	 * 当服务窗口为客户服务时,客户管理机器要把该客户从等待服务的客户队列中移除。
	 */
	public String fetchCustomer(String name){
		return ServerNumberQueue.valueOf(name).fetchNumber(); 
	}
	/*
	 * 添加客户到队列中
	 */
	public void generateCustomer(String name){
		String mes;
		mes = ServerNumberQueue.valueOf(name).generateNumber();
		System.err.println("'" + mes + "'来了.");
	}
}

     服务窗口(ServiceWindow)

public class ServiceWindow {
	private String windowName;//服务窗口名
	private String windowType;//服务窗口类型
	private int windowNumber;//窗口号
	private ServerNumberMachine snm;
	private ExecutorService pool;

	public ServiceWindow(int number) {
		this(ConstantsUnit.COMMON_CUSTOMER, number);
	}

	public ServiceWindow(String type, int number) {
		this.windowType = type;
		this.windowName = type;
		this.windowNumber = number;
		this.snm = ServerNumberMachine.getInstance();
		this.pool = ThreadPool.getInstance().getExecutorService();
	}

	public void setWindowName(String windowName) {
		this.windowName = windowName;
	}

	public void setWindowNumber(int windowNumber) {
		this.windowNumber = windowNumber;
	}

	public int getWindowNumber() {
		return this.windowNumber;
	}

	private boolean service() {
		return service(windowType);
	}
	/*
	 * 查找客户并为客户服务功能
	 */
	private boolean service(String type) {
		/*try {
			Thread.sleep(2000);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}*/
		Random time = new Random();
		//当前服务窗口sleep时间,以模拟为客户服务耗时。当为快速客户服务时,时间为1;否则随机产生一个时间
		int servicetime = type.equals(ConstantsUnit.FAST_CUSTOMER) ? 
				ConstantsUnit.MIN_SERVICE_TIME
				: time.nextInt(ConstantsUnit.MAX_SERVICE_TIME
						- ConstantsUnit.MIN_SERVICE_TIME)
						+ ConstantsUnit.MIN_SERVICE_TIME + 1;
		String servicemess;
		servicemess = snm.fetchCustomer(type);
		if (servicemess != null) {
			try {
/*				System.out.println(windowName + windowNumber + "正在为'"
						+ servicemess + "'服务");*/
				long stime = System.currentTimeMillis();
				Thread.sleep(servicetime);
				long etime = System.currentTimeMillis();
				System.out.println(windowName + windowNumber + "为'"
						+ servicemess + "'服务完毕,耗时:" + (etime - stime) / 1000
						+ "秒.");
				return true;
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
/*		if(type.equals(ConstantsUnit.COMMON_CUSTOMER)){
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}*/
		return false;
	}
	/*
	 * 调用此方法让窗口开始服务
	 *   VIP,快速窗口没有相应的客户时,要服务普通客户
	 */
	public void startService() {
		pool.execute(new Runnable() {
			@Override
			public void run() {
				while (true) {
					switch (windowType) {
					/*
					 * VIP窗口成功为VIP客户服务则要继续判断是否有VIP客户等待服务,否则判断是否有等待服务的
					 *   普通客户,有则要为普通客户服务
					 */
					case "VIP":
						if(service())//将查找客户并服务单独封装成一个方法,调用service方法
							break;
						service(ConstantsUnit.COMMON_CUSTOMER);
						break;
						/*
						 * 快速窗口成功为快速客户服务则要继续判断是否有VIP客户等待服务,否则判断是否有等待服务的
						 *   普通客户,有则要为普通客户服务
						 */
					case "FAST":
						if(service())
							break;
						service(ConstantsUnit.COMMON_CUSTOMER);
						break;
					case "COMMON":
						service();
					}
				}
			}
		});
	}

}

     用到的一些常(ConstantsUnit)

public class ConstantsUnit {
	public static int MAX_SERVICE_TIME = 10000;//最大服务时间,毫秒
	public static int MIN_SERVICE_TIME = 1000;//最小服务时间
	public static String VIP_CUSTOMER = "VIP";
	public static String COMMON_CUSTOMER = "COMMON";
	public static String FAST_CUSTOMER = "FAST";
	public static int GENERATE_CUSTOMER = 1;//产生普通客户的时间间隔

}

     测试功能否完成(Test)

public class Test {
	public static void main(String[] args){
		
		final ServerNumberMachine snm = ServerNumberMachine.getInstance();
		
		ThreadPool pool = ThreadPool.getInstance();
		
		
		for(int i=1; i<=4; i++){
//			System.out.println("创建普通服务窗口...");
			new ServiceWindow(i).startService();
		}
//		System.out.println("创建快速服务窗口...");
		new ServiceWindow(ConstantsUnit.FAST_CUSTOMER, 5).startService();
//		System.out.println("创建VIP服务窗口...");
		new ServiceWindow(ConstantsUnit.VIP_CUSTOMER, 6).startService();
		
		//产生普通客户
		pool.getScheduledExecutorService().scheduleAtFixedRate(
				new Runnable(){
					@Override
					public void run() {
						snm.generateCustomer(ConstantsUnit.COMMON_CUSTOMER);
					}
				}, 
				0, 
				ConstantsUnit.GENERATE_CUSTOMER, 
				TimeUnit.SECONDS);
		//产生VIP客户
		pool.getScheduledExecutorService().scheduleAtFixedRate(
				new Runnable(){
					@Override
					public void run() {
						snm.generateCustomer(ConstantsUnit.VIP_CUSTOMER);
					}
				}, 
				0, 
				ConstantsUnit.GENERATE_CUSTOMER*6, 
				TimeUnit.SECONDS);
		//产生快速客户
		pool.getScheduledExecutorService().scheduleAtFixedRate(
				new Runnable(){
					@Override
					public void run() {
						snm.generateCustomer(ConstantsUnit.FAST_CUSTOMER);
					}
				}, 
				0, 
				ConstantsUnit.GENERATE_CUSTOMER*2, 
				TimeUnit.SECONDS);
	}

}

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值