《黑马程序员》 银行业务调度系统回顾总结

------- android培训java培训、期待与您交流! ----------

 在做银行业务调度系统这个题目的时候,我们是需要了解一下银行业务办理的流程的:

   通常情况下是这样的,我们去银行取钱的时候,需要先去取号机器上取号(就相当于我们站在服务窗口前排队一样,只是有了取号机器,它知道用户取到了哪个号码为止了,而服务窗口就根据我们的取的号码来依次为我们服务)

  所以通过上面的分析,我们知道,在整个银行里面只有一个号码机器,而银行的业务窗口又分为普通,快速(这个可以办理交水电费和还贷的业务),VIP(钱多的可以用这个)
  快速窗口和VIP窗口,它们在没有业务的时候也是可以帮普通的客户进行服务的。
  所以,我们总结了一下,这里的对象,应该有如下几个:
     号码管理器: 它的作用是管理它所产生号码:
       它有两个用处:
            一个是提供号码给客户取号,排队使用。
            一个是提供号码给服务窗口使用,因为服务窗口要从号码管理器那里知道该为哪个客户服务了。
     号码机器:
         它的内部管理了三种类型的号码管理器,普通,快速,VIP。三种
        因为在整个银行中,只有一台号码机器。所以它在程序中设计的时候是要做成单例的。
     然后就是服务窗口,它要根据自己是哪种类型的窗口去找号码机器,找它里面的号码管理器。问他该为哪个号码服务了。 这里在设计号码管理器的时候,是通过集合的形式来实现的。因为号码机器产生了号码之后,用户会取走一个号码,然后再产生就是下一个数了,我们在用户取号的时候,把用户取走的那个号码按队列的形式添加到这个集合中,而服务窗口在取号的时候,就是从集合中取的。服务窗口在取号的时候,是从队列的第0个位置开始取走的。即取走了集合中的第一个元素。
        因为号码管理器中,是两个方法都是在操作同一个集合,所以我们要让两个方法互斥,即同时只能有一个方法操作集合。
  ----------------------------------------------------
  需要注意的细节如下:    
 我们在这个题目中是使用JDK 1.5的那套线程库,我们使用的Executors并发库。
     线程池
Executors.newSingleThreadExecutor().execute(new Runnable() {@Override
  public void run() {
    //线程所要执行的任务
     }
        });      
 开启了一个线程池,线程池中只有一个线程,我们是把任务交给线程池,由线程池去池中挑选空闲的线程,把任务交给他去执行。而不是我们把任务直接交给某个线程去执行。
     调度池
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                int number = NumberMachine2.getInstance().getCommonManager()
                        .genrateNewNumber();
                System.out.println(number + "号普通客户等待服务");

            }
        }, 0, Constants2.INTERVAL_TIME2, TimeUnit.SECONDS);
  这里列出一个调度池,里面是用于定时调度的,它可以定于某个时间干一件事情,也可以定在一段时间干一件之后,然后再过一段时间再执行这件事情。这有点像生活中的定时炸弹的原理。
      ----------------------------------------------------
  在模拟客户进入营业厅的时候,分析如下:
   vip:express:common
     6:  2:       1
      我们这么来分析:普通客户来2个,快速客户来1个
      普通客户来6个,VIP客户才来1个。
 
  我们在模拟给服务服务的时候,是让线程随机进行休眠的,是使用随机数来实现的,随机数中的nextInt的值是取于10000-1000的即最大随机数,9000,使用随机数之后起作用的就是0-8999,然后+1即1-9000,然后+1000即1-10000
    ----------------------------------------------------    
  因为我们的服务窗口只有三种类型的:普通,快速,VIP我们可以使用枚举来操作 我们使用name()它的作用是返回此枚举变量的名称,就是我们在枚举类中定义的变量的名称

      ------------------------------------------------------------------------- 

public class NumberManager2 {
	private List<Integer> queue = new ArrayList<Integer>();
	private int lastNumber = 1;

	public synchronized Integer genrateNewNumber() {
		queue.add(lastNumber);
		return lastNumber++; //第一次返回1,第二次返回2
	}

	public synchronized Integer featchNumber() {
		Integer number=null;
		if(queue.size()>0){
			number=queue.remove(0);
		}
		return number;
	}
}

public class NumberMachine2 {
	private NumberManager2 commonManager = new NumberManager2();
	private NumberManager2 expressManager = new NumberManager2();
	private NumberManager2 vipManager = new NumberManager2();

	public NumberManager2 getCommonManager() {
		return commonManager;
	}

	public NumberManager2 getExpressManager() {
		return expressManager;
	}

	public NumberManager2 getVipManager() {
		return vipManager;
	}

	private NumberMachine2() {
	}

	public static NumberMachine2 getInstance() {
		return instance;
	}

	private static NumberMachine2 instance = new NumberMachine2();
}

public class ServiceWindow2 {
	private Customer2Type type = Customer2Type.COMMON; // 窗口的类型
	private int windowId = 1; // 窗口的编号

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

	public void setWindowId(int windowId) {
		this.windowId = windowId;
	}

	public void start() {
		Executors.newSingleThreadExecutor().execute(new Runnable() {
			@Override
			public void run() {
				while (true) {
					switch (type) {
					case COMMON:
						commonService();
						break;
					case EXPRESS:
						expressService();
						break;
					case VIP:
						vipService();
						break;
					}
				}
			}
		});
	}

	// 普通客户
	private void commonService() {
		Integer number = NumberMachine2.getInstance().getCommonManager()
				.featchNumber();
		System.out.println("第" + windowId + "个" + type + "窗口开始获取普通任务");
//		System.out.println("commonservicenumber:" + number);
		if (number != null) {
			System.out.println("第" + windowId + "个" + type + "窗口准备为第" + number
					+ "个普通客户服务");
			long beginServiceTime2 = System.currentTimeMillis();
			int maxRandom = Constants2.MAX_SERVICE_TIMES
					- Constants2.MIN_SERVICE_TIMES;
			long serviceTimes2 = new Random().nextInt(maxRandom) + 1
					+ Constants2.MIN_SERVICE_TIMES;
			try {
				Thread.sleep(serviceTimes2);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			long coastServiceTime2 = System.currentTimeMillis()
					- beginServiceTime2;
			System.out.println("第" + windowId + "个" + type + "窗口准备为第" + number
					+ "个普通客户完成服务,耗时:" + coastServiceTime2 / 1000 + "秒");
		} else {
			System.out.println("第" + windowId + "个" + type
					+ "窗口没有获取到普通任务,需要休息1秒");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	// 快速客户
	private void expressService() {
		String windowName = "第" + windowId + "个" + type + "窗口";
		Integer number = NumberMachine2.getInstance().getExpressManager()
				.featchNumber();
		System.out.println(windowName + "开始获取快速业务");
//		System.out.println("expressServiceNumber:" + number);
		if (number != null) {
			System.out.println(windowName + "准备为第" + number + "个快速客户服务");
			long beginServiceTime2 = System.currentTimeMillis();
			// int maxRandom = Constants2.MAX_SERVICE_TIMES
			// - Constants2.MIN_SERVICE_TIMES;
			// long serviceTimes2 = new Random().nextInt(maxRandom) + 1
			// + Constants2.MIN_SERVICE_TIMES;
			try {
				Thread.sleep(Constants2.MIN_SERVICE_TIMES);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			long coastServiceTime2 = System.currentTimeMillis()
					- beginServiceTime2;
			System.out.println("第" + windowId + "个" + type + "窗口准备为第" + number
					+ "个快速客户完成服务,耗时:" + coastServiceTime2 / 1000 + "秒");
		} else {
			System.out.println("第" + windowId + "个" + type
					+ "窗口没有获取到快速任务,可以为普通用户服务");
			commonService();
		}
	}

	// VIP客户
	private void vipService() {
		String windowName = "第" + windowId + "个" + type + "窗口";
		Integer number = NumberMachine2.getInstance().getVipManager()
				.featchNumber();
		System.out.println(windowName + "开始获取VIP业务");
//		System.out.println("vipServiceNumber:" + number);
		if (number != null) {
			System.out.println(windowName + "准备为第" + number + "个VIP客户服务");
			long beginServiceTime2 = System.currentTimeMillis();
			int maxRandom = Constants2.MAX_SERVICE_TIMES
					- Constants2.MIN_SERVICE_TIMES;
			long serviceTimes2 = new Random().nextInt(maxRandom) + 1
					+ Constants2.MIN_SERVICE_TIMES;
			try {
				Thread.sleep(serviceTimes2);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			long coastServiceTime2 = System.currentTimeMillis()
					- beginServiceTime2;
			System.out.println("第" + windowId + "个" + type + "窗口准备为第" + number
					+ "个VIP客户完成服务,耗时:" + coastServiceTime2 / 1000 + "秒");
		} else {
			System.out.println("第" + windowId + "个" + type
					+ "窗口没有获取到VIP任务,可以为普通用户服务");
			commonService();
		}
	}

}

public class Constants2 {
	public static int MAX_SERVICE_TIMES=10000;
	public static int MIN_SERVICE_TIMES=1000;
	
	public static int INTERVAL_TIME2=1;
}

public enum Customer2Type {
	COMMON, EXPRESS, VIP;
	
	public String toString(){
		switch(this){
		case COMMON:
			return "普通";
		case EXPRESS:
			return "快速";
		case VIP:
			return name();
		}
		return null;
	}
}
/**
	 * @param args
	 */
	public static void main(String[] args) {
		// 创建窗口对象
		for (int i = 1; i < 5; i++) {
			ServiceWindow2 commonServcie = new ServiceWindow2();
			commonServcie.setWindowId(i);
			commonServcie.start();
		}

		ServiceWindow2 expressService = new ServiceWindow2();
		expressService.setType(Customer2Type.EXPRESS);
		expressService.start();

		ServiceWindow2 vipService = new ServiceWindow2();
		vipService.setType(Customer2Type.VIP);
		vipService.start();

		// 模拟客户
		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				int number = NumberMachine2.getInstance().getCommonManager()
						.genrateNewNumber();
				System.out.println(number + "号普通客户等待服务");

			}
		}, 0, Constants2.INTERVAL_TIME2, TimeUnit.SECONDS);

		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				int number = NumberMachine2.getInstance().getExpressManager()
						.genrateNewNumber();
				System.out.println(number + "号快速客户等待服务");

			}
		}, 0, Constants2.INTERVAL_TIME2 * 2, TimeUnit.SECONDS);

		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				int number = NumberMachine2.getInstance().getVipManager()
						.genrateNewNumber();
				System.out.println(number + "号VIP客户等待服务");

			}
		}, 0, Constants2.INTERVAL_TIME2 * 6, TimeUnit.SECONDS);
	}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值