黑馬程序員_7k面試題之銀行業務調度系統

銀行業務調度系統

               ------ 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學習型技術博客、期待與您交流! ----------
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章