zoukankan      html  css  js  c++  java
  • 银行业务调度系统

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

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

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

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

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

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

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

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

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

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

    分析:

    对象:客户,取号机(取号、叫号),服务窗口。

    客户:分为普通客户、快速客户和VIP客户(使用枚举),本身不需要方法。

    号码机(NumberMachine取号、叫号):

    包括产生号码功能(generateNumber,为客户提供号码)和叫号功能(fetchNumber);号码的存储需要容器,使用ArrayList;客户有三种类型,则取到的号码也有三种类型(对不同的客户提供不同类型的服务),分别编号存储,所以需要三台号码机。

    号码机管理器(NumberManager):用于管理号码机,且只需要一台,用于管理三种客户类型的号码机,设计为单例。

    服务窗口(ServiceWindow):为客户办理业务。普通窗口有多个,快速窗口和VIP窗口可以根据需要设计。普通窗口只为普通客户提供服务,快速窗口和VIP窗口在空闲时可以为普通客户服务。服务窗口依次叫号,由于号码由号码机产生,故要向号码机询问是否有需要服务的客户。

    package mycode.bank;
    
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    
    public class MainClass {
    	public static void main(String[] args) {
    		for(int i=1;i<5;i++){
    			ServiceWindow commonWindow=new ServiceWindow();
    			commonWindow.setWindowID(i);
    			commonWindow.start();
    		}
    		
    		ServiceWindow expressWindow=new ServiceWindow();
    		expressWindow.setType(CustomerTypes.EXPRESS);//在此处设置type,可能会出现明明是快速窗口为第3号普通客户服务,却输出快速窗口为第3号快速客户服务
    		//解决方法见ServiceWindow类的commonService方法
    		expressWindow.start();
    		
    		ServiceWindow vipWindow=new ServiceWindow();
    		vipWindow.setType(CustomerTypes.VIP);
    		vipWindow.start();
    		
    		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable(){
    			public void run(){
    				Integer number=NumberManager.getInstance().getCommonMachine().generateNumber();
    				System.out.println(number+"普通客户正在等待服务");
    			}
    		}, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME, TimeUnit.SECONDS);
    		
    		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable(){
    			public void run(){
    				Integer number=NumberManager.getInstance().getExpressMachine().generateNumber();
    				System.out.println(number+"快速客户正在等待服务");
    			}
    		}, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME*2, TimeUnit.SECONDS);
    		
    		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable(){
    			public void run(){
    				Integer number=NumberManager.getInstance().getVipMachine().generateNumber();
    				System.out.println(number+"VIP客户正在等待服务");
    			}
    		}, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME*6, TimeUnit.SECONDS);
    	}
    }
    
    package mycode.bank;
    
    import java.util.Random;
    import java.util.concurrent.Executors;
    
    public class ServiceWindow {
    	private CustomerTypes type = CustomerTypes.COMMON;// 决定窗口的类型,默认为普通窗口
    	private int windowID = 1;
    
    	public void setType(CustomerTypes type) {
    		this.type = type;
    	}
    
    	public void setWindowID(int windowID) {
    		this.windowID = windowID;
    	}
    
    	public void start() {// 叫号
    		Executors.newSingleThreadExecutor().execute(new Runnable() {
    			public void run() {
    				while (true) {
    					switch (type) {
    					case COMMON:
    						commonService();
    						break;
    					case EXPRESS:
    						expressService();
    						break;
    					case VIP:
    						vipService();
    						break;
    					}
    				}
    			}
    
    			private void commonService() {
    				String windowName = windowID + "号" + type + "窗口";
    				Integer number = NumberManager.getInstance().getCommonMachine()
    						.fetchNumber();
    				System.out.println(windowName + "正在获取普通客户");
    				if (number != null) {
    					System.out.println(windowName + "正在为" + number + "号" + "普通"
    							+ "客户服务");// 如果这里调用type的话,
    					// express和vip窗口为普通客户服务时,type会设置为express和vip,而不再是common
    					long beginTime = System.currentTimeMillis();
    					int maxRandom = Constants.MAX_SERVICE_TIME
    							- Constants.MIN_SERVICE_TIME;
    					long serviceTime = new Random().nextInt(maxRandom) + 1
    							+ Constants.MIN_SERVICE_TIME;// 1000-10000ms
    					try {
    						Thread.sleep(serviceTime);
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    					long costTime = System.currentTimeMillis() - beginTime;
    					System.out.println(windowName + "为" + number
    							+ "号普通客户完成服务,耗时" + costTime / 1000 + "秒");
    				} else {
    					System.out.println(windowName + "没有获取到普通客户,休息一秒钟");
    					try {
    						Thread.sleep(1000);
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    				}
    			}
    
    			private void expressService() {
    				String windowName = windowID + "号" + type + "窗口";
    				Integer number = NumberManager.getInstance()
    						.getExpressMachine().fetchNumber();
    				System.out.println(windowName + "正在获取客户");
    				if (number != null) {
    					System.out.println(windowName + "正在为" + number + "号" + type
    							+ "客户服务");
    					long beginTime = System.currentTimeMillis();
    					long serviceTime = Constants.MIN_SERVICE_TIME;
    					try {
    						Thread.sleep(serviceTime);
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    					long costTime = System.currentTimeMillis() - beginTime;
    					System.out.println(windowName + "为" + number + "号" + type
    							+ "客户完成服务,耗时" + costTime / 1000 + "秒");
    				} else {
    					System.out.println(windowName + "没有获取到" + type + "客户");
    					commonService();
    				}
    			}
    
    			private void vipService() {
    				String windowName = windowID + "号" + type + "窗口";
    				Integer number = NumberManager.getInstance().getVipMachine()
    						.fetchNumber();
    				System.out.println(windowName + "正在获取客户");
    				if (number != null) {
    					System.out.println(windowName + "正在为" + number + "号" + type
    							+ "客户服务");
    					long beginTime = System.currentTimeMillis();
    					int maxRandom = Constants.MAX_SERVICE_TIME
    							- Constants.MIN_SERVICE_TIME;
    					long serviceTime = new Random().nextInt(maxRandom) + 1
    							+ Constants.MIN_SERVICE_TIME;
    					try {
    						Thread.sleep(serviceTime);
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    					long costTime = System.currentTimeMillis() - beginTime;
    					System.out.println(windowName + "为" + number
    							+ "号"+type+"客户完成服务,耗时" + costTime / 1000 + "秒");
    				} else {
    					System.out.println(windowName + "没有获取到"+type+"客户");
    					commonService();
    				}
    			}
    		});
    
    	}
    }
    
    package mycode.bank;
    
    public class NumberManager {
    	private NumberMachine commonMachine=new NumberMachine();
    	private NumberMachine expressMachine=new NumberMachine();
    	private NumberMachine vipMachine=new NumberMachine();
    	
    	public NumberMachine getCommonMachine() {
    		return commonMachine;
    	}
    	public NumberMachine getExpressMachine() {
    		return expressMachine;
    	}
    	public NumberMachine getVipMachine() {
    		return vipMachine;
    	}
    	// 将对象变成单例(号码机器只能存在一个,用于管理多个号码管理器)
    	private NumberManager(){
    		// 构造函数私有化
    	}
    	
    	private static NumberManager instance=new NumberManager();// 静态,对象未创建之前就要存在
    	public static NumberManager getInstance(){ // 构造函数私有化,外部不能通过本类创建对象,只能通过静态方法调用
    		return instance;
    	}
    }
    
    package mycode.bank;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class NumberMachine {
    	private int lastnumber=1;// 上次返回的号码
    	private List<Integer> queueNumber=new ArrayList<Integer>();// 排队的号码
    	
    	/*两个不同的线程访问相同的数据,需要互斥*/
    	public synchronized Integer generateNumber(){
    		//使用Integer,自动拆箱、装箱,故lastNumber即使是int型也无所谓
    		queueNumber.add(lastnumber);
    		return lastnumber++;
    	}
    	
    	public synchronized Integer fetchNumber(){// 取号
    		Integer number=null;
    		if(queueNumber.size()>0){
    			number=queueNumber.remove(0);// 取出排在最前的号码,返回值就是被移除的号码
    		}
    		return number;
    	}
    }
    
    package mycode.bank;
    
    public enum CustomerTypes {
    	COMMON,EXPRESS,VIP;
    
    	@Override
    	public String toString() {
    		String name=null;
    		switch(this){
    		case COMMON:
    			name="普通";
    			break;
    		case EXPRESS:
    			name="快速";
    			break;
    		case VIP:
    			name="VIP";
    			break;
    		}
    		return name;
    	}
    	
    	
    }
    
    package mycode.bank;
    
    public class Constants {
    	public static int MAX_SERVICE_TIME=10000;
    	public static int MIN_SERVICE_TIME=1000;
    	public static int COMMON_CUSTOMER_INTERVAL_TIME=1;
    }
  • 相关阅读:
    HDU 2433 Travel (最短路,BFS,变形)
    HDU 2544 最短路 (最短路,spfa)
    HDU 2063 过山车 (最大匹配,匈牙利算法)
    HDU 1150 Machine Schedule (最小覆盖,匈牙利算法)
    290 Word Pattern 单词模式
    289 Game of Life 生命的游戏
    287 Find the Duplicate Number 寻找重复数
    283 Move Zeroes 移动零
    282 Expression Add Operators 给表达式添加运算符
    279 Perfect Squares 完美平方数
  • 原文地址:https://www.cnblogs.com/chenchong/p/2679245.html
Copyright © 2011-2022 走看看