黑馬程序員-銀行業務調度系統

                                         ---------- android培訓  java培訓   期待與您交流!------------

 

先上需求:

 

 

銀行業務調度系統

 

模擬實現銀行業務調度系統邏輯,具體需求如下:

 

       銀行內有6個業務窗口,1- 4號窗口爲普通窗口,5號窗口爲快速窗口,6號窗口爲VIP窗口。

 

       有三種對應類型的客戶:VIP客戶,普通客戶,快速客戶(辦理如交水電費、電話費之類業務的客戶)。

 

       異步隨機生成各種類型的客戶,生成各類型用戶的概率比例爲:

 

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

 

        客戶辦理業務所需時間有最大值和最小值,在該範圍內隨機設定每個VIP客戶以及普通客戶辦理業務所需的時間,快速客戶辦理業務所需時間爲最小值(提示:辦理業務的過程可通過線程Sleep的方式模擬)。

 

        各類型客戶在其對應窗口按順序依次辦理業務。

 

        當VIP(6號)窗口和快速業務(5號)窗口沒有客戶等待辦理業務的時候,這兩個窗口可以處理普通客戶的業務,而一旦有對應的客戶等待辦理業務的時候,則優先處理對應客戶的業務。

 

        隨機生成客戶時間間隔以及業務辦理時間最大值和最小值自定,可以設置。

 

        不要求實現GUI,只考慮系統邏輯實現,可通過Log方式展現程序運行結果。

 

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

 

分析:

         客戶進入銀行先分類型取票排隊,然後等待服務窗口叫號。所以我覺得計數器應該擁有客戶排隊的數據,那麼編號就當作是一個個客戶,計數器就擁有對外訪問客戶的方法,而窗口就向計數器詢問有沒有下一個客戶,如果沒有就換普通類型再詢問有沒有,如果始終沒有下一個客戶,那麼就休息一下再繼續

        快速窗口和vip窗口在沒有對應客戶的情況下還要爲普通客戶服務。所以窗口類中應該有判斷類型的方法

        由於服務的時間有最大值和最小值,爲了體現面向對象的思想,就將時間封裝成一個類。

 

下面就進行代碼的分析,自己沒有照着老師教的抄,而是以自己的思想做一遍,體會其中的差距,理解老師每一步爲什麼要那麼做。

最後總結分析出自己雖然也能將代碼做出來,但沒有將任何事物看作對象來對待,面向對象的體會也許就只能在實際的項目經驗中去積累。

窗口類型:

/**
 * 由於窗口類型是不變的,分別對應 普通 快速 VIP
 * @author 不信
 *
 */
public enum windowType {
	COMMON,FAST,VIP;
	
	//覆蓋父類的toString()
	public String toString()
	{
		switch (this) {
		case COMMON:
			return "普通";
		case FAST:
			return "快速";
		default:
			return name();
		}
	}
	
	//用戶類型對應服務時間,其中快速客戶爲最小值也就是1秒
	public int useTime()
	{
		if(this != FAST)
			return Constants.MAX_SERVICE_TIME;
		else {
			return Constants.MIN_SERVICE_TIME;
		}
	}
}

 

服務時間的最大值和最小值:

/**
 * 服務時間的最小值與最大值
 * @author 不信
 *
 */
public class Constants {
	public static int MAX_SERVICE_TIME = 10; //10秒!
	public static int MIN_SERVICE_TIME = 1; //1秒!
}



計數器,裏面包含了客戶的排隊順序

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

/**
 * 這是一個計數器類,由於顧客領了票就說明排了隊,所以計數器擁有顧客
 * 服務窗口可以問計數器有沒有顧客
 * 
 * */
public class counter {
	
	//顧客排隊的號
	private int num = 1;
	
	//顧客類型不一樣,辦理業務所用的時間也就不一樣
	private int time;
	
	//顧客類型
	private windowType type;
	
	//存儲顧客排隊的號
	private LinkedList<Integer> list = new LinkedList<Integer>();
	
	
	//計數器類是一開始就有類型與辦理業務所需的最大時間
	public counter(int time,windowType type)
	{
		this.time = time;
		this.type = type;
		addList();
	}
	
	//定時進入一位顧客,由於顧客類型的不一樣,光臨的時間也不一樣
	public synchronized void addList()
	{
		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
				new Runnable() {
					
					@Override
					public void run() {
						list.addLast(num++);
					}
				},
				0,
				time,
				TimeUnit.SECONDS
				);
		System.out.println("第"+num+"位"+type.toString()+"客戶等待服務");
	}
	
	//服務窗口調用這個方法來獲取正在排隊的客戶,如果沒有返回null
	public synchronized Integer take()
	{
		if(!list.isEmpty())
			return list.removeFirst();
		else {
			return null;
		}
	}
		
}


三種窗口類型對應了三種客戶類型

/**
 * 三種客戶類型的對象,提供對外訪問的靜態方法,服務窗口其實就是根據類型來訪問的
 * @author 不信
 *
 */
public class client {
	private static counter COMMONCLIENT = new counter(1, windowType.COMMON);
	private static counter FASTCLIENT = new counter(3,windowType.FAST);
	private static counter VIPCLIENT = new counter(6, windowType.VIP);
	
	private client(){}
	
	public static counter getClient(windowType type)
	{
		switch (type) {
		case COMMON:
			return COMMONCLIENT;
		case FAST:
			return FASTCLIENT;
		default:
			return VIPCLIENT;
		}
	}
	


 

服務窗口

import java.util.Random;
import java.util.concurrent.Executors;
/**
 * 服務窗口類
 * @author 不信
 *
 */
public class window {
	
	//每個窗口都有自己對應的類型
	private windowType type;
	
	//每個窗口都有自己的編號
	private int num;
	
	//在初始化時,就有了類型和編號
	public window(windowType type, int num)
	{
		this.type = type;
		this.num = num;
	}
	
	//窗口開始工作
	public void windower()
	{
		System.out.println("第"+num+"號"+this.type+"窗口開始服務");
		
		//創建一個線程池,其中只有一個線程
		Executors.newSingleThreadExecutor().execute(new Runnable() {
			
			@Override
			public void run() {
				while(true)
				{
					System.out.println("第"+num+"號"+window.this.type+"窗口正在等待客戶");
					
					//調用窗口的工作內容
					work(type);
				}
			}
		});
	}
	
	//窗口工作的內容
	public void work(windowType type)
	{
		//窗口尋找對應類型的客戶是否存在,如果存在就給予服務,如果不存在就執行 else if()
		Integer i = client.getClient(type).take();
		if(i!=null){
			System.out.println("第"+num+"號"+this.type+"窗口正在爲第"+i+"位"
					+type+"客戶服務");
			
			//以客戶的類型計算出要給服務的時間
			int randomTime = new Random().nextInt(type.useTime())+1;
			try {
				//這裏以線程 sleep()的形式模仿
				Thread.sleep(randomTime*1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			//當線程“醒”來時,就給對應得客戶服務完畢
			System.out.println("第"+num+"號"+this.type+"窗口爲第"+i+"位"
					+type+"客戶服務耗時"+randomTime+"秒");
		}
		
		//由於vip窗口和快速窗口在沒有對應客戶存在的情況下,還要給普通客戶服務所以這裏使用了遞歸
		else if(type != windowType.COMMON)
		{
			work(windowType.COMMON);	
		}
		else{
			
			//如果始終沒有需要服務的客戶,就sleep()休息一秒,醒來繼續查找
			System.out.println("第"+num+"號"+this.type+"窗口沒有取到任務,正在休息一秒");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
}


最後主函數調用:

public class MainClass {
	public static void main(String[] args)
	{
		
		//四個普通窗口
		for(int i = 1;i < 5;i++)
		{
			new window(windowType.COMMON, i).windower();
		}
		
		//一個快速窗口 和一個VIP窗口
		new window(windowType.FAST, 5).windower();
		new window(windowType.VIP, 6).windower();
	}
}
 
 

運行結果如圖

 

                                          ----------  android培訓  java培訓    期待與您交流!------------

                                                              詳情請點擊:http://edu.csdn.net/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章