黑马程序员_7k面试题之银行业务调度系统

时间:2023-02-18 09:43:00

银行业务调度系统

               ------ android培训java培训java学习型技术博客、期待与您交流! ----------

模拟实现银行业务调度系统逻辑,具体需求如下:

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

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

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

 * VIP客户 :普通客户 :快速客户  =  1 3

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

快速客户办理业务所需时间为最小值(提示:办理业务的过程可通过线程Sleep的方式模拟)。

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

 * VIP6号)窗口和快速业务(5号)窗口没有客户等待办理业务的时候,这两个窗口可以处理普通客户的业务,

而一旦有对应的客户等待办理业务的时候,则优先处理对应客户的业务。

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

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

思路:

    名次提炼法,分析需要哪些对象,也就是需要定义的类:

每一个客户其实就是由银行的一个取号机器产生号码的方式来表示的,每一个号码代表一个客户。由于有三类客

    户CustomerTypeVIP客户,普通客户,快速客户 

所以定义一个取号机NumberMachine,取号机生成三种不同类型的号码为三种客户服务。所以取号机有三个对应

    客户类型的对象NumberManager,生成不同的号码。

号码机器在整个系统中始终只能有一个,所以,它要被设计成单例。该类提供获取NumberMachine对象方法。

NumberManager类有生产号码和获取号码的方式,并且将生成的号码添加到类中定义的集合里。

各类型客户在其对应窗口按顺序依次办理业务 SerivceWindow,准确地说,应该是窗口依次叫号,服务窗口每次找

    号码管理器获取当前要被服务的号码。

那么,所需要的对象有:NumberMacineNumberManagerServiceWindowCustomerTypeMainClassConstants

步骤:

    NumberMachine类:

NumberMachine类设计成单例。

定义三个成员变量分别指向三个NumberManager对象,表示普通、快速和VIP客户的号码管理器,对外提供获取对象

    的方法

    NumberManager类:

定义一个用于存储上一个客户号码的成员变量和用于存储所有等待服务的客户号码的队列集合。

定义一个产生新号码的方法和获取马上要为之服务的号码的方法,这两个方法被不同的线程操作了相同的数据,

    所以,要进行同步。

    CustomerType枚举类:定义三个客户类型

系统中有三种类型的客户,所以用定义一个枚举类,其中定义三个成员固定表示表示三种类型的客户。

重写toString方法,返回类型的中文名称。这是在后面编码时重构出来的,刚开始不用考虑。

    ServiceWindow类:定义三种 服务窗口

窗口应该有服务类型windowType和窗口编号属性windowId.

windowType应该和客户类型是一致的,默认指向普通类型,但是对外提供获取和设置窗口类型的方法,因为普通窗

    口也可能为其它窗口

定义一个start方法,内部启动一个线程,根据服务窗口的类别分别循环调用三个不同的方法。 

定义三个方法分别对三种客户进行服务,为了观察运行效果,应详细打印出其中的细节信息。

客户办理业务时间有最大和最小,所以定义一个Constants类,表示最大和最小值

    Constants

这是一个常量类,客户办理业务时间的最大和最小值。并假定生成普通客户的间隔值

定义三个常量:MAX_SERVICE_TIMEMIN_SERVICE_TIMECOMMON_CUSTOMER_INTERVAL_TIME

    MainClass类:运行程序

for循环创建出4个普通窗口,再创建出1个快速窗口和一个VIP窗口。

接着再创建三个定时器,分别定时去创建新的普通客户号码、新的快速客户号码、新的VIP客户号码。

public class NumberMachine1 {		//取号机类
    private NumberMachine1() {};	//取号机设计成单例模式,并对外提供获取对象的方式
    private static NumberMachine1 instance = new NumberMachine1();
    public static NumberMachine1 getInstace() {
	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;
    }
}


public class NumberManager1 {		//号码管理器类,
    private List<Integer> queueNumber = new ArrayList<Integer>();
    private int serviceNumber = 0;	//定义服务号码
	
    //这两个方法同时操作共享数据serviceNumber,且被不同线程调用,需同步
	//叫号,服务号码不能为0,所以自增后添加到集合中
    public synchronized Integer generateServiceNumber() {	
	queueNumber.add(++serviceNumber);										
	return serviceNumber;										
    }
	//取号,如果集合不为空,就取出服务号码
    public synchronized Integer fetchServiceNumber() {		
	Integer number = null;										
	if(queueNumber.size() > 0) {
		number = queueNumber.remove(0);			
	}
	return number;
    }
}


public enum CustomerType1 {	//定义客户类型枚举,客户只有固定的三种类型
    COMMON,EXPRESS,VIP;		
	
    public String toString() {	//复写enum类中的toString(),将客户类型转换成字符串
	String name = null;		
	switch(this) {			
	case COMMON:
	    name = "普通";
	    break;
	case EXPRESS:
	    name = "快速";
	    break;
	case VIP:
	    name = name();	//枚举的name()方法返回与枚举对名称对应的字符串
	    break;
	}
	return name;
    }
}


public class ServiceWindow1 {	//服务窗口类
    private CustomerType1 windowType = CustomerType1.COMMON;
    private int windowId = 1;
    public void setWindowType(CustomerType1 windowType) {
	this.windowType = windowType;
    }
    public CustomerType1 getWindowType() {
	return windowType;
    }
    public void setWindowId(int windowId) {
	this.windowId = windowId;
    }
	
    public void startService() {//开始服务
	Executors.newSingleThreadExecutor().execute(new Runnable() {
	    public void run() {
		while(true) {		//无限循环
		    switch(windowType) {
		    case COMMON:	//如果是普通客户,就到普通窗口办理业务
			commonService();
			break;
	  	    case EXPRESS:	//如果是快速客户,就到快速窗口办理业务
			expressService();
			break;
		    case VIP:		如果是VIP客户,就到VIP窗口办理业务
			vipService();
		    }
		}
	    }
	});
    }
	
    private void commonService() {//普通客户服务
	String windowName = windowId + "号" + windowType + "窗口";
	Integer serviceNumber = NumberMachine.getInstance().getCommomManager().fetchServiceNumber();
	System.out.println(windowName + "开始获取普通任务");
	if(serviceNumber != null) {
	    System.out.println(windowName + "开始为 " + serviceNumber + " 号普通客户服务");
	    int serviceTime = new Random().nextInt(Constants1.MAX_SERVICE_TIME) + 1;
	    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() {//快速客户服务
	String windowName = windowId + "号" + windowType + "窗口";
	Integer serviceNumber = NumberMachine.getInstance().getExpressManager().fetchServiceNumber();
	System.out.println(windowName + "开始获取快速任务");
	if(serviceNumber != null) {
	    System.out.println(windowName + "开始为 " + serviceNumber + " 号快速客户服务");
	    int serviceTime = Constants1.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() {	//VIP客户服务
	String windowName = windowId + "号" + windowType + "窗口";
	Integer serviceNumber = NumberMachine.getInstance().getVipManager().fetchServiceNumber();
	System.out.println(windowName + "开始获取VIP任务");
	if(serviceNumber != null) {
	    System.out.println(windowName + "开始为 " + serviceNumber + " 号VIP客户服务");
	    int serviceTime = new Random().nextInt(Constants1.MAX_SERVICE_TIME) + 1;
	    try {
		Thread.sleep(serviceTime);
	    } catch (InterruptedException e) {
		e.printStackTrace();
	    }
	    System.out.println(windowName + "为" + serviceNumber + "号VIP客户完成服务,耗时:" + serviceTime/1000 + "秒");
	} else {
	    System.out.println(windowName + "没有取到VIP任务");
	    commonService();		//如果vip窗口没有客户办理业务为,就为普通客户服务
	}
    }
}


public class Constants1 {	//定义常量类
    public static int MAX_SERVICE_TIME = 10000;		//办理业务所需时间最大值
    public static int MIN_SERVICE_TIME = 1000;		//办理业务所需时间最小是
    public static int COMMON_CUSTOMER_INTERVAL_TIME = 1;//普通客户产生的间隔时间
}


public class MainClass1 {
    public static void main(String[] args) {
	for (int i = 1; i < 5; i++) {			//产生四个普通窗口,并开始服务
	    ServiceWindow1 commonwindow = new ServiceWindow1();
	    commonwindow.setWindowId(i);
	    commonwindow.startService();
	}
		
	ServiceWindow1 expressWindow = new ServiceWindow1();//产生1个快速窗口,并开始服务
	expressWindow.setWindowType(CustomerType1.EXPRESS);
	expressWindow.setWindowId(5);
	expressWindow.startService();
		
	ServiceWindow1 vipWindow = new  ServiceWindow1();	//产生1个vip窗口,并开始服务
	vipWindow.setWindowType(CustomerType1.VIP);
	vipWindow.setWindowId(6);
	vipWindow.startService();
		
	Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
	    new Runnable() {
	        public void run() {
		   Integer serviceNumber = NumberMachine.getInstance().getCommomManager().genericNewNumber();
		   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().genericNewNumber();
		    System.out.println(serviceNumber + "号快速客户正在等待服务");
		}
	    }, 
	    0, 
	    Constants.COMMON_CUSTOMER_INTERVAL_TIME * 2, 
	    TimeUnit.SECONDS);
		
	Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
	    new Runnable() {
	        public void run() {
		    Integer serviceNumber = NumberMachine.getInstance().getVipManager().genericNewNumber();
		    System.out.println(serviceNumber + "号VIP客户正在等待服务");
		}
	    }, 
	    0, 
	    Constants.COMMON_CUSTOMER_INTERVAL_TIME * 6,
	    TimeUnit.SECONDS);
	}
}


               ------ android培训java培训java学习型技术博客、期待与您交流! ----------