銀行業務調度系統
---------------------------------------------------------------------------------------------------------------------------------------------
銀行系統
個人分析案例的思路就是,把可能是對象的都拿出來分析一下,看誰具有特殊數據提供什麼方法:
比如這個項目中,涉及到:
人、取號機、窗口
人:就是客戶,來銀行就是辦業務,但是業務是窗口(銀行)提供的
取號機分:提供 個人、vip、快速 三種排隊方式,說明其具備 爲3種方式排隊的功能。
窗口分:普通窗口1-4個、vip 1個、快速1個 提供客戶辦理的業務功能
OK ,人要排隊,就得去取號機取票:也就是說,取號機生成的號碼,等同於客戶,也就是說,人不是關鍵對象
取號機生成不同的號碼,號碼存放到一個集合中,號碼等待,
個人分析案例的思路就是,把可能是對象的都拿出來分析一下,看誰具有特殊數據提供什麼方法:
比如這個項目中,涉及到:
人、取號機、窗口
人:就是客戶,來銀行就是辦業務,但是業務是窗口(銀行)提供的
取號機分:提供 個人、vip、快速 三種排隊方式,說明其具備 爲3種方式排隊的功能。
窗口分:普通窗口1-4個、vip 1個、快速1個 提供客戶辦理的業務功能
OK ,人要排隊,就得去取號機取票:也就是說,取號機生成的號碼,等同於客戶,也就是說,人不是關鍵對象
取號機生成不同的號碼,號碼存放到一個集合中,號碼等待,
顯然,這個時候,需要一個能保證唯一的 類來進行管理這三組取號機【】設計一個單列模式來管理【】三種客戶各是一組取號機,各有一個集合 也就是形成了三組 取號機,由一個管理機管理
窗口呼叫各種號碼,側等同於把集合中第一個號碼移除
新增客戶,就是給集合add元素。
【】窗口 需要呼叫號碼,取得對應客戶的服務 那麼內部就應該封裝着 對3種客戶的處理機制
【】Main new 出 4個普通窗口,1個vip 窗口 1個快速窗口
啓動 3個定時器 對應三種客戶人羣的到來(開始生成號碼),開始頻率的工作
-----------------------
【1】
package com.isoftstone.interview.bank;
/**銀行排號系統-1----- 取號機
1、new號
2、窗口取號
*/
import java.util.*;
public class NumberManager {
private int lastNumber = 1;
private List<Integer> queneNumber = new ArrayList<Integer>();
//1 取號 表示新來一個客戶
public synchronized Integer generteNewNumber(){
queneNumber.add(lastNumber);
return lastNumber++;
}
//2 窗口叫號,那麼等待的號碼,應該在一個集合中,叫一個則移除一個
public synchronized Integer fetchNumber(){
Integer number = null;
if(queneNumber.size()>0){
return number = queneNumber.remove(0);
}
else{
return number;
}
}
//3 處理的是同一個數據,所以必須要同步
}
//NumberManager end
小結論:
1、單獨看着是一個取號的機器,具備2個功能,
1、給客戶排隊小票
2、給窗口提供排隊號
2、客戶手中的號,也就是集合中的號,和窗口拿出去的號,必須一直,也就是需要同步
【2】
package com.isoftstone.interview.bank;
/**銀行排號系統-2----- 號碼管理器
1、三組客戶--3組取號機
2、唯一性
*/
public class NumberMachine {
//1 創建3個客戶號碼管理器
private NumberManager CommonManager = new NumberManager();
private NumberManager VIPManager = new NumberManager();
private NumberManager ExpressManager = new NumberManager();
//2 生成 get 方法
public NumberManager getCommonManager() {
return CommonManager;
}
public NumberManager getVIPManager() {
return VIPManager;
}
public NumberManager getExpressManager() {
return ExpressManager;
}
//3 【】 把本類設計爲單列。
private NumberMachine(){}
private static NumberMachine instance = new NumberMachine();
public static NumberMachine getInstance(){
return instance;
} //single end
}
//NumberMachine end
小結:
1、new出三組 取號機 對應三種客戶
1、生成 對應是取號方法
2、唯一性肯定就是單列模式了。
1、私有構造方法2、覆蓋getInstance方法3、私有對象,返回對象
【3】
package com.isoftstone.interview.bank;
/***銀行排號系統-3----- 窗口
1、對外只有一個方法
2、內部封裝了 3種客戶處理機制
1、普通客戶處理機制
2、快速
3、VIP
3、3種機制雷同,當快速和VIP無客戶時,應調用普通客戶機制
4、進行客戶選擇時,使用 枚舉和switch 是估錯的組合
5、學會 把常量集中放置在一個類中
*/
import java.util.Random;
import java.util.concurrent.Executors;
public class ServiceWindow {
//4-0、 定義一個類型,類型只有三種,>>建立枚舉類
private CustomerType type = CustomerType.COMMON;
//6、定義窗口序列號、默認1
private int windowId = 1;
//7、爲4-0和6 生成 set 方法
public void setType(CustomerType type) {
this.type = type;
}
public void setWindowId(int windowId) {
this.windowId = windowId;
}
//1、對外只有一個功能;統稱辦業務
public void start(){
//2、內部封裝好的線程
Executors.newSingleThreadExecutor().execute(new Runnable(){
public void run() {
while(true){
//3、這個時候是獲取普通客戶?VIP?快速?所以要定義一個類型
switch(type){
case COMMON:
commonService();
break;
case EXPRESS:
expressService();
break;
case VIP:
vipService();
break;
}
}
}
});
}
//20 可以把17-19 的代碼進行優化 最後來完成
// 17 把功能封裝成 方法。 --【普通客戶】
private void commonService() {
//8 展示 幾號窗口正在爲什麼客戶服務
//9 看 CustomerType 枚舉類
String windowName = "第"+windowId+"號"+type+"窗口"+""+"";
//5、展示 信息 應該顯示那個窗口第幾個窗口在獲取什麼樣的任務
Integer number = NumberMachine.getInstance().getCommonManager().fetchNumber();
System.out.println(windowName+"正在獲取任務");
//4-1、對獲取到的服務號碼進行判斷,null表示還沒有等待客戶
if(number != null){
System.out.println(windowName+"正在爲"+number+"號"+"【普通客】服服務");
long beginTime = System.currentTimeMillis();//開始記時
//11、模擬服務--服務時間的區間
//12、根據題目,設置一個常量的區間
//13、創建 Constants 常量類
//14、設定服務時間隨機爲 1-10秒之間(普通:1-10、快速:1 VIP:1-10)
int MaxRand = Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME;
long serveTime = new Random().nextInt(MaxRand)+1+Constants.MIN_SERVICE_TIME;//在1-10 秒之間
try {
Thread.sleep(serveTime);//15、睡眠時間,代表正在給客戶處理業務。
} catch (InterruptedException e) {
e.printStackTrace();
}//模擬服務 end
long costTime = System.currentTimeMillis()-beginTime;//耗費時間
//10、展示 那個窗口爲那個客戶完成服務 以及所耗時間
System.out.println(windowName+"爲"+number+"號"+"普通客戶完成服務耗時:"+(costTime)/1000+"秒");
}
else{
System.out.println(windowName+"沒有取到服務任務...休息3秒");
//16、如果沒有服務--睡眠3秒 表示 等待時間
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}//common end
// 18 把功能封裝成 方法。 --【快速客戶】
private void expressService() {//18-1 更改爲: expressService
String windowName = "第"+windowId+"號"+type+"窗口";
Integer number = NumberMachine.getInstance().getExpressManager().fetchNumber();//18-2 更改爲:getExpressManager();
System.out.println(windowName+"正在獲取任務");
if(number != null){
System.out.println(windowName+"正在爲"+number+"號【"+type+"客戶】服務");
long beginTime = System.currentTimeMillis();
try {
Thread.sleep(Constants.MIN_SERVICE_TIME);//18-3 更改爲:最小值
} catch (InterruptedException e) {
e.printStackTrace();
}
long costTime = System.currentTimeMillis()-beginTime;
System.out.println(windowName+"爲"+number+"個"+type+"客戶完成服務耗時:"+(costTime)/1000+"秒");//18-4:type 對應當前窗口客戶
}
else{
System.out.println(windowName+"沒有【"+type+"】客戶等待");
//18-5【】 更改爲: 沒有當前窗口的服務時、 處理普通窗口的人物
commonService();
}
}//common end
// 19 把功能封裝成 方法。 --【VIP客戶】
private void vipService() {//19-1 更改爲: vipService()//getVIPManager()
String windowName = "第"+windowId+"號"+type+"窗口";
Integer number = NumberMachine.getInstance().getVIPManager().fetchNumber();//19-2 更改爲:getVIPManager()
System.out.println(windowName+"正在獲取任務");
if(number != null){
System.out.println(windowName+"正在爲"+number+"號【"+type+"客戶】服務");
long beginTime = System.currentTimeMillis();
int MaxRand = Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME;
long serveTime = new Random().nextInt(MaxRand)+1+Constants.MIN_SERVICE_TIME;//在1-10 秒之間
try {
Thread.sleep(serveTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
long costTime = System.currentTimeMillis()-beginTime;
System.out.println(windowName+"爲"+number+"號"+type+"客戶完成服務耗時:"+(costTime)/1000+"秒");//19-3:type 對應當前窗口客戶
}
else{
System.out.println(windowName+"沒有【"+type+"】客戶等待");
//19-4【】 更改爲: 沒有當前窗口的服務時、 處理普通窗口的人物
commonService();
}
}//common end
}
// ServiceWindow end
小結
1、固定範圍的東西,可以定義爲枚舉
2、常量應該集中到一個類中存貯
3、發現 new Random() 和Thread.sleep(); switch 時常組合在一起。
【4】
package com.isoftstone.interview.bank;
/**銀行排號系統-4----- 枚舉 三種客戶信息*/
public enum CustomerType {
//9 【】 ServiceWindow 類中第9 步 覆蓋toString 返回中文信息
COMMON,VIP,EXPRESS;
//1覆蓋toString 返回對應的中文 對應MainClass類
public String toString(){
switch(this){
case COMMON:
return "普通";
case EXPRESS:
return "快速";
case VIP:
return name();
}
return null;
}
}
//CustomerType end
小結
1、枚舉可以通過 toString 返回枚舉對應的值
2、枚舉很強大,多多學習
【5】
package com.isoftstone.interview.bank;
/**銀行排號系統-5----- 常量信息*/
public class Constants {
//13 【】ServiceWindow 類中第13步 設定常量
//13-1最大時間 10s
public static int MAX_SERVICE_TIME = 10000;
//13-2最小時間 1s
public static int MIN_SERVICE_TIME = 1000;
//10 【】MainClass 類中 第10步,設定一個常量
public static int COMMON_CUSTOMER_INTERVAL_TIME = 1;
}
//Constants end
小結
1、常量通常都是大寫多個單詞用_分割開
2、常量一定是public 修飾的 必須是static 可以是 final
【6】
package com.isoftstone.interview.bank;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**銀行排號系統-6----- Main */
public class MainClass {
public static void main(String[] args) {
//1、new出3種窗口
//2、4個【普通窗口】
for(int i=1;i<5;i++){
//2-1 創建 普通窗口
ServiceWindow commonWindow = new ServiceWindow();
//2-2 設定窗口編號
commonWindow.setWindowId(i);
//2-3 啓動窗口
commonWindow.start();
}
//3、new1個【快速窗口】
ServiceWindow expressWindow = new ServiceWindow();
//3-1 設定 窗口的類型 而不是窗口的編號 --該窗口只有1個
expressWindow.setType(CustomerType.EXPRESS);
expressWindow.start();
//4、new1個【VIP窗口】
ServiceWindow vipWindow = new ServiceWindow();
//4-1 設定 窗口的類型
vipWindow.setType(CustomerType.VIP);
vipWindow.start();
//------------------------------
//5 模擬3種客戶 來取號
//6 創建三組 --- 線程池-- 啓動一個定時器
//7、common 【普通客戶】
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable(){
public void run(){
//11、來普通客人,也就是叫號
Integer number = NumberMachine.getInstance().getCommonManager().generteNewNumber();
System.out.println("第"+number+"號 普通客戶"+"等待服務");
}
},
0, // 啓動時,就開始運營
//1, // 間隔 1秒 啓動一次run 功能 產生1個普通客戶,客戶比例:6:3:1 6秒6個
//10-1、使用常量來表示 生成客戶的比例
Constants.COMMON_CUSTOMER_INTERVAL_TIME,
TimeUnit.SECONDS // 設定前2者的 尺量單位爲 秒。
);// common end
//8、express 【快速客戶】
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable(){
public void run(){
//12、來快速客人,也就是叫號
Integer number = NumberMachine.getInstance().getExpressManager().generteNewNumber();
System.out.println("第"+number+"號 快速客戶"+"等待服務");
}
},
0, // 啓動時,就開始運營
//2, // 6秒 3個
//10-2、使用常量來表示 生成客戶的比例
Constants.COMMON_CUSTOMER_INTERVAL_TIME * 2,
TimeUnit.SECONDS // 設定前2者的 尺量單位爲 秒。
);// common end
//9、vip 【VIP客戶】
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable(){
public void run(){
//13、來VIP客人,也就是叫號
Integer number = NumberMachine.getInstance().getVIPManager().generteNewNumber();
System.out.println("第"+number+"號 VIP客戶"+"等待服務");
}
},
0, // 啓動時,就開始運營
//6, // 6秒1個 完成 比例生成客戶
//10-3、使用常量來表示 生成客戶的比例
Constants.COMMON_CUSTOMER_INTERVAL_TIME * 6,
TimeUnit.SECONDS // 設定前2者的 尺量單位爲 秒。
);// common end
}// 13 main end
}
// MainClass end
小結:
1、通過 new 表示對象的個數
2、注意 普通窗口new出來是 setWindowId()
而VIP和快速 則是 setType()
3、啓動3組定時器 四個參數分別是:
1、定時器主要功能2、定時器第一次啓動時間3、定時器頻率時間4、 2個時間的時間單位5、TimeUnit 是一個枚舉,封裝的是時間單位6、Executors.newScheduledThreadPool(1).scheduleAtFixedRate
創建一個只有1線程的定時器。
7、Executors 線程池很強大。多多學習
4、好像就寫完了。
5、測試
5、測試
7、做代碼,真的是要多練,這個系統,第一次看完視頻,第二次試着不到50分鐘就做完了
但是調試就花了一個多小時吃了飯,又繼續做,然後半小時搞定,沒有錯誤。而且,人都是剛學的時候,記憶很好,能寫出來過個三五天什麼的,就不行了,畢竟閱歷不夠,見識不多,敲的代碼太少了。
上圖:
---------------------------------------------------------------------------------------------------------------------------------------------
----------
android培訓、 java培訓
、期待與您交流!----------
----------------------------------------------