黑马程序员------经典面试之银行调度系统

          ------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

一千个人眼中有一千个哈姆雷特。没次看一套学习视频总会有不一样的收获,这次也是一样,简单的业务,仍然有很多值得学的地方。

银行业务调度系统需求如下:

6个业务窗口 1-4号为普通窗口 5号为快速窗口 6号为VIP窗口

客户 VIP 普通客户 快速客户(缴费)

异步随机生成各种类型客户 各种客户的比例:V C F 1:6:3

客户办理业务的时间有最大值和最小值,该范围内随机设定每个VIP客户以及
普通客户办理业务所需的时间,快速客户办理业务所需时间为最小值

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

当VIP6号窗口和快速5号窗口没有对应的客户等待办理业务的时候则处理普通客户的业务
一旦有对应的客户等待则优先处理对应客户的业务

随机生成客户时间间隔以业务办理时间最大值和最小值

客户都是由区号机器产生的 要有号码管理器对象不断的产生新的号码就等于产生了新的客户

由于有三类客户,三类客户之间是独立的就要有三个号码管理器,号码管理器由同一的机器管理

服务窗口要找号码管理器去当前要被服务的客户

 

这种需求如果不用面向对象的思维去设计会使代码看起来很笨重、繁杂,听了老师的这讲视频之后又对面向对象设计有了一点新的认识:

视频中老师强调了很多次的面向对象的思想:谁拥有数据谁就要对外提供改变调用数据的方法。

一下就是银行调度系统的具体实现:

客户要不停的产生,客户的编号要对应唯一的一个客户,对此有了一下的客户管理器的类

package com.tai.bank;

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

/**
 * 号码管理器
 * @author Tai
 */
public class NubmerManager
{
	/**
	 * 新产生的客户号码
	 */
	private int lastNumber = 1;
	/**
	 * 客户等待的队列
	 */
	private List<Integer> queueNuber = new ArrayList<Integer>();
	
	/**
	 * 产生新客户
	 * @return 新客户的号码
	 */
	public synchronized Integer generateNewManager(){
		queueNuber.add(lastNumber);
		return lastNumber++;
	}
	
	/**
	 * 取号
	 * @return  最前面的客户的号码
	 */
	public synchronized Integer fetchServiceNuber(){
		if (queueNuber.size()>0)
		{
			return queueNuber.remove(0);
		}
		return null;
	}
	
	/*
	 * generateNewManager fetchServiceNuber两个方法同时操作相同的数据
	 * 多线程的时候容易产生并发的问题,故此这里要使用synchronized关键字互斥
	 */
}

银行业务员(窗口)要得到当前正在等待的用户,而几种客户都是由一个叫号器产生的,这里就要有一个单例的号码机器类统一为三种不同类型的客户提供被调用的方法

package com.tai.bank;

/**
 * 号码机器
 * @author Tai
 */
public class NumberMachine
{
	private NubmerManager commenManager = new NubmerManager();
	private NubmerManager expressManager = new NubmerManager();
	private NubmerManager vipManager = new NubmerManager();
	private static NumberMachine numberMachine = new NumberMachine();
	
	private NumberMachine(){}
	
	public static NumberMachine getInstance(){
		return numberMachine;
	}
	
	public NubmerManager getCommenManager(){
		return commenManager;
	}
	public NubmerManager getExpressManager(){
		return expressManager;
	}
	public NubmerManager getVipManager(){
		return vipManager;
	}
}

三种不同的用户类型,类型是固定的,对此将客户类型设计成枚举类型使用比较方便:

package com.tai.bank;
/**
 * 客户类型的枚举 
 * 
 * switch语句可以直接使用枚举
 * 
 * @author Tai
 *
 */
public enum CustomerType
{
	COMMON,EXPRESS,VIP;
	/**
	 * 复写toString方法 使用更加方便
	 */
	public String toString() {
		switch (this)
		{
		case COMMON:
			return "普通";
		case EXPRESS:
			return "快速";
		case VIP:
			return "VIP";
		default:
			break;
		}
		return null;
	}
}

银行业务员处理客户的请求,银行中的业务窗口就相当于业务员,处理过程总使用到了新线程,这里使用线程池能更加安全,高效的处理多线程问题:

package com.tai.bank;

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

public class ServiceWindow{

	/**
	 * 窗口类型
	 */
	private CustomerType type = CustomerType.COMMON;
	private int windowId = 1;
	public void setType(CustomerType type)
	{
		this.type = type;
	}

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

	public void start(){
		Executors.newSingleThreadExecutor().execute(new Runnable(){
			@Override
			public void run(){
				String WindowName = "第" + windowId + "号" + type + "窗口";
				while (true)
				{
					switch (type)
					{
					case COMMON:
						commonService(WindowName);
						break;
					case EXPRESS:
						expressService(WindowName);
						break;
					case VIP:
						vipService(WindowName);
						break;
						
					default:
						break;
					}
					
				}
			}
		});
	}

	private void commonService(String WindowName)
	{
		
		Integer number = NumberMachine.getInstance().getCommenManager().fetchServiceNuber();
		System.out.println(WindowName+"正在获取任务");
		if (null!=number){
			    System.out.println(WindowName + "正在为第" + number+"个"+ "普通客户服务");
				long beginTime = (int) System.currentTimeMillis(); 
				int maxSerciceTime = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME; 
				//处理时长
				long serveTime = new Random().nextInt(maxSerciceTime) + 1 +Constants.MIN_SERVICE_TIME;
				try
				{
					Thread.sleep(serveTime);
				}
				catch (InterruptedException e)
				{
					e.printStackTrace();
				}
				long endTime = (int) System.currentTimeMillis() - beginTime; 
				System.out.println(WindowName + "为第" + number+"个"+ "普通完成服务,耗时"+endTime/1000+"秒");
		}else{
			System.out.println(WindowName +"没有取到服务任务,休息一秒钟");
			try
			{
				Thread.sleep(1000);
			}
			catch (InterruptedException e)
			{
				e.printStackTrace();
			}
		}
	}
	
	private void expressService(String WindowName)
	{
		
		Integer number = NumberMachine.getInstance().getExpressManager().fetchServiceNuber();
		System.out.println(WindowName+"正在获取任务");
		if (null!=number){
				System.out.println(WindowName + "正在为第" + number+"个"+type + "客户服务");
				long beginTime = (int) System.currentTimeMillis(); 
				//处理时长
				long serveTime = Constants.MIN_SERVICE_TIME;
				try
				{
					Thread.sleep(serveTime);
				}
				catch (InterruptedException e)
				{
					e.printStackTrace();
				}
				long endTime = (int) System.currentTimeMillis() - beginTime; 
				System.out.println(WindowName + "为第" + number+"个"+type + "客户完成服务,耗时"+endTime/1000+"秒");
		}else{
			commonService(WindowName);
		}
	}
	
	private void vipService(String WindowName)
	{
		Integer number = NumberMachine.getInstance().getVipManager().fetchServiceNuber();
		System.out.println(WindowName+"正在获取任务");
		if (null!=number){
			System.out.println(WindowName + "正在为第" + number+"个"+type + "客户服务");
				long beginTime = (int) System.currentTimeMillis(); 
				//处理时长
				long serveTime = Constants.MAX_SERVICE_TIME;
				try
				{
					Thread.sleep(serveTime);
				}
				catch (InterruptedException e)
				{
					e.printStackTrace();
				}
				long endTime = (int) System.currentTimeMillis() - beginTime; 
				System.out.println(WindowName + "为第" + number+"个"+type + "客户完成服务,耗时"+endTime/1000+"秒");
		}else{
			commonService(WindowName);
		}
	}
	
	
}

接下来就是主类,此类调用产生客户的方法,处理客户请求的方法:

package com.tai.bank;

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

public class MainClass
{
	public static void main(String[] args)
	{
		for (int i = 0; i < 5; i++)
		{
			ServiceWindow commonWindow = new ServiceWindow(); 
			commonWindow.setWindowId(i);
			commonWindow.start();
		}
		ServiceWindow vipWindow = new ServiceWindow();
		vipWindow.setType(CustomerType.VIP);
		vipWindow.start();
		
		ServiceWindow expressWindow = new ServiceWindow();
		expressWindow.setType(CustomerType.EXPRESS);
		expressWindow.start();
		
		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable()
		{
			@Override
			public void run()
			{
				Integer number = NumberMachine.getInstance().getCommenManager().generateNewManager();
				System.out.println("第" + number + "号普通客户等待服务");
			}
		},0,Constants.COMMON_CUSTUMER_INTERVAL_TIME,TimeUnit.SECONDS);
		
		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable()
		{
			@Override
			public void run()
			{
				Integer number = NumberMachine.getInstance().getVipManager().generateNewManager();
				System.out.println("第" + number + "号vip客户等待服务");
			}
		},0,Constants.VIP_CUSTUMER_INTERVAL_TIME,TimeUnit.SECONDS);
		
		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable()
		{
			@Override
			public void run()
			{
				Integer number = NumberMachine.getInstance().getExpressManager().generateNewManager();
				System.out.println("第" + number + "号快速客户等待服务");
			}
		},0,Constants.EXPRESS_CUSTUMER_INTERVAL_TIME,TimeUnit.SECONDS);
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值