【黑馬程式設計師】7K面試題之銀行排程系統
模擬實現銀行業務排程系統邏輯,具體需求如下:
Ø 銀行內有6個業務視窗,1- 4號視窗為普通視窗,5號視窗為快速視窗,6號視窗為VIP視窗。
Ø 有三種對應型別的客戶:VIP客戶,普通客戶,快速客戶(辦理如交水電費、電話費之類業務的客戶)。
Ø 非同步隨機生成各種型別的客戶,生成各型別使用者的概率比例為:
VIP客戶 :普通客戶 :快速客戶 = 1 :6 :3。
Ø 客戶辦理業務所需時間有最大值和最小值,在該範圍內隨機設定每個VIP客戶以及普通客戶辦理業務所需的時間,快速客戶辦理業務所需時間為最小值(提示:辦理業務的過程可通過執行緒Sleep的方式模擬)。
Ø 各型別客戶在其對應視窗按順序依次辦理業務。
Ø 當VIP(6號)視窗和快速業務(5號)視窗沒有客戶等待辦理業務的時候,這兩個視窗可以處理普通客戶的業務,而一旦有對應的客戶等待辦理業務的時候,則優先處理對應客戶的業務。
Ø 隨機生成客戶時間間隔以及業務辦理時間最大值和最小值自定,可以設定。
Ø 不要求實現GUI,只考慮系統邏輯實現,可通過Log方式展現程式執行結果。
需求分析:
基本邏輯:
客戶:來到銀行後,先取號。取號後等待視窗喊號。然後到相應視窗辦理好業務後離開銀行。
視窗:根據順序喊號,為客戶辦理好業務後,按照順序繼續喊號。視窗為三種類型,對應視窗為對對應客戶服務。
號碼產生管理器:客戶來到銀行後按順序給客戶產生排隊號。然後把號碼分配給各個視窗。這個號碼管理產生器為單例(即只有一個)。即使有多個取號機器,但是多個取號機器操作的是“唯一”的一個號碼管理器。
專案所需類:
視窗類:ServiceWindow
視窗有ID、型別等一系列屬性;
視窗建立後,開始自動工作。不斷檢視客戶列表是否有客戶,有的話為列表第一個客戶辦理業務,然後稍微休息一下繼續為下一位客戶辦理業務;如果沒有客戶,也稍微休息一下然後繼續看有沒有客戶到來。
號碼產生管理器:package com.itcast; import com.itcast.NumberManager; import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ServiceWindow { int windowID;//視窗ID UserType windowType=null;//視窗型別 String windowTypeName="";//視窗型別名字 String userTypeName="";//客戶型別名字 int maxRandom=Constants.MAX_BUSINESS_TIME-Constants.MIN_BUSINESS_TIME;//業務隨機時間 public ServiceWindow(){} public ServiceWindow(int windowID,UserType windowType){ this.windowID=windowID; this.windowType=windowType; ExecutorService pool= Executors.newSingleThreadExecutor(); pool.execute( new Runnable(){ public void run(){ while(true){ windowTypeName=NumberManager.getInstance().getUserType(ServiceWindow.this.windowType); if(NumberManager.getInstance().userNumbeList.size()==0 && NumberManager.getInstance().userExpressNumbeList.size()==0 && NumberManager.getInstance().userVipNumbeList.size()==0){ System.out.println("當前還沒有客戶前來辦理業務!"+ServiceWindow.this.windowID+"號"+windowTypeName+"視窗狀態空閒!"); try { Thread.sleep(10000);//休息10秒鐘 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }else{ User user=NumberManager.getInstance().remove(ServiceWindow.this.windowID,ServiceWindow.this.windowType); if(user!=null){ userTypeName=NumberManager.getInstance().getUserType(user.getUserType()); int businessTime=0; try { switch (user.getUserType()) { case COMMONUSER: //普通客戶辦理業務需要用時,在最大值和最小值之間 businessTime=new Random().nextInt(ServiceWindow.this.maxRandom)+1+Constants.MIN_BUSINESS_TIME; Thread.sleep(businessTime); break; case EXPRESSUSER: //快速客戶辦理月舞的速度最快 businessTime=Constants.MIN_BUSINESS_TIME; Thread.sleep(businessTime); break; case VIPUSER: //VIP客戶辦理業務需要用時,在最大值和最小值之間 businessTime=new Random().nextInt(ServiceWindow.this.maxRandom)+1+Constants.MIN_BUSINESS_TIME; Thread.sleep(businessTime); break; default: break; } System.out.println(user.getNumber()+"號"+userTypeName+"客戶在"+ServiceWindow.this.windowID+"號"+windowTypeName+"視窗辦理完業務啦!用時:"+businessTime/1000+"."+businessTime%1000+"秒"); System.out.println("業務辦理完成休息5秒!"); Thread.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } } ); } }
為客戶產生排隊號碼,當視窗索要號碼時,把號碼給視窗後,刪除本號碼。每隔一段時間自動產生客戶和號碼。我這裡為了檢視系統處理很多各種各樣的客戶會不會出現bug,設定了每一秒產生一個客戶。
package com.itcast;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class NumberManager {
private static NumberManager numberManager=null;
List<User> userNumbeList=new ArrayList<User>();//普通號碼的客戶列表
List<User> userExpressNumbeList=new ArrayList<User>();//快速號碼的客戶列表
List<User> userVipNumbeList=new ArrayList<User>();//VIP號碼的客戶列表
static int number=0;
static int expressNumber=0;
static int vipNumber=0;
public synchronized void add(User user){
userNumbeList.add(user);
}
public synchronized User remove(int windowID,UserType windowType){
User user=null;
switch (windowType) {
case COMMONUSER:
if(userNumbeList.size()!=0){
user=userNumbeList.remove(0);
System.out.println("請"+user.getNumber()+"號普通客戶到"+windowID+"號普通視窗辦理業務!"+windowID+"號普通視窗開始為"+user.getNumber()+"號普通客戶辦理業務。");
System.out.println();
}
return user;
case EXPRESSUSER:
if(userExpressNumbeList.size()!=0){
//如果快速客戶列表有客戶的話執行快速叫號程式
user=userExpressNumbeList.remove(0);
System.out.println("請"+user.getNumber()+"號快速客戶到"+windowID+"號快速視窗辦理業務!"+windowID+"號快速視窗開始為"+user.getNumber()+"號快速客戶辦理業務。");
System.out.println();
}else{
//如果快速客戶列表沒有快速客戶就檢視普通客戶列表有沒有客戶
if(userNumbeList.size()!=0){
//如果有就叫號普通客戶到快速視窗進行業務操作
user=userNumbeList.remove(0);
System.out.println("當前"+windowID+"號快速客戶視窗無人,請"+user.getNumber()+"號普通客戶到"+windowID+"號快速視窗辦理業務!"+windowID+"號快速視窗開始為"+user.getNumber()+"號普通客戶辦理業務。");
System.out.println();
}
}
return user;
case VIPUSER:
if(userVipNumbeList.size()!=0){
//如果VIP客戶列表有客戶的話執行VIP叫號程式
user=userVipNumbeList.remove(0);
System.out.println("請"+user.getNumber()+"號VIP客戶到"+windowID+"號VIP視窗辦理業務!"+windowID+"號VIP視窗開始為"+user.getNumber()+"號VIP客戶辦理業務。");
System.out.println();
}else{
//如果VIP客戶列表沒有快速客戶就檢視普通客戶列表有沒有客戶
if(userNumbeList.size()!=0){
//如果有就叫號普通客戶到VIP視窗進行業務操作
user=userNumbeList.remove(0);
System.out.println("當前"+windowID+"號VIP客戶視窗無人,請"+user.getNumber()+"號普通客戶到"+windowID+"號VIP視窗辦理業務!"+windowID+"號VIP視窗開始為"+user.getNumber()+"號普通客戶辦理業務。");
System.out.println();
}
}
return user;
default:
break;
}
return user;
}
private NumberManager(){
ExecutorService pool= Executors.newSingleThreadExecutor();
pool.execute(
new Runnable(){
public void run(){
while(true){
try {
//(new Random().nextInt(10)+1)*1000
Thread.sleep(1000);//隨機(1-10)秒後產生一個客戶
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int random =new Random().nextInt(10)+1;
switch (random) {
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
number++;
System.out.println("歡迎第"+number+"位普通客戶來到黑馬銀行!");
userNumbeList.add(new User(UserType.COMMONUSER,number));
break;
case 7:
case 8:
case 9:
expressNumber++;
System.out.println("歡迎第"+expressNumber+"位快速客戶來到黑馬銀行!");
userExpressNumbeList.add(new User(UserType.EXPRESSUSER,expressNumber));
break;
case 10:
vipNumber++;
System.out.println("歡迎第"+vipNumber+"位VIP客戶來到黑馬銀行!");
userVipNumbeList.add(new User(UserType.VIPUSER,vipNumber));
break;
default:
break;
}
}
}
}
);
}
public static NumberManager getInstance(){
if (numberManager==null){
//新增鎖,使多執行緒同步更安全
synchronized(NumberManager.class){
if (numberManager==null){
numberManager=new NumberManager();
}
}
}
return numberManager;
}
public String getUserType(UserType userType){
String userTypeName="";
switch (userType) {
case COMMONUSER:
userTypeName="普通";
return userTypeName;
case EXPRESSUSER:
userTypeName="快速";
return userTypeName;
case VIPUSER:
userTypeName="VIP";
return userTypeName;
default:
break;
}
return userTypeName;
}
}
視窗為客戶辦理業務的時間範圍Constants:
這是一個配置檔案類。以後只需要在這個類中修改時間就能控制辦理業務時間範圍。
1000等於1秒,最小值不得小於1000;
package com.itcast;
public class Constants {
//業務所用的時間最大值和最小值
public static int MAX_BUSINESS_TIME=10000;
public static int MIN_BUSINESS_TIME=3000;
}
使用者類:User
封裝了客戶的一些基本資訊。便於操作。
package com.itcast;
public class User {
private String name="王瑞亞";
private int number;
private UserType userType;
public UserType getUserType() {
return userType;
}
public void setUserType(UserType userType) {
this.userType = userType;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public String getName() {
return name;
}
User(){}
User(UserType userType,int number){
this.userType=userType;
this.number=number;
}
}
視窗型別和客戶型別列舉類UserType:
package com.itcast;
public enum UserType {
COMMONUSER,EXPRESSUSER,VIPUSER;
}
main方法類,程式開始的地方BankMain:
package com.itcast;
public class BankMain {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
NumberManager nm=NumberManager.getInstance();
for(int i=1;i<5;i++){
//迴圈建立四個普通視窗
new ServiceWindow(i,UserType.COMMONUSER);
}
new ServiceWindow(1,UserType.EXPRESSUSER);//建立一個快速客戶視窗
new ServiceWindow(1,UserType.VIPUSER);//建立一個VIP視窗
}
}
專案總結:
用了一個晚上思考如果實現邏輯和架構,第二天上午寫程式,下午修改bug,我還沒有達到張老師一氣呵成的功力!還需努力!
這是一個模擬現實中銀行業務邏輯的一個小程式,這個專案培養了我對專案需求的分析,以及對專案的構架。一個程式不是功能都完成了就算寫完了,還要審視程式的架構,是否是一個健壯的系統,是否易於擴充套件,是否處理了各種突發情況,程式是否人性化等等。這樣才能不斷的成長,從運用自己的java技術到合理的運用達到最大好處,這是一個轉變。現在我還沒有能力拿到一個專案就能馬上構架好這個專案的框架。我給自己定了一個職業規劃:三年內達到專案經理的水平,當上總監,或創業或當一名老師(由於對張孝祥老師的敬佩,決定跟隨他)。
接下來我打算花功夫學習學習軟體的設計和資料結構,從而設計完美的程式碼。
閱盡天下程式碼,心中自然有碼。
下面把控制檯輸出結果放出來,本人測試很多遍了目前沒有發現bug,大家可以複製程式碼在自己機器執行試試,如果有錯誤的話請大家聯絡我在修改。我的QQ1659881336.謝謝啦!
當前還沒有客戶前來辦理業務!1號普通視窗狀態空閒!
當前還沒有客戶前來辦理業務!2號普通視窗狀態空閒!
當前還沒有客戶前來辦理業務!4號普通視窗狀態空閒!
當前還沒有客戶前來辦理業務!3號普通視窗狀態空閒!
當前還沒有客戶前來辦理業務!1號快速視窗狀態空閒!
當前還沒有客戶前來辦理業務!1號VIP視窗狀態空閒!
歡迎第1位普通客戶來到黑馬銀行!
歡迎第2位普通客戶來到黑馬銀行!
歡迎第3位普通客戶來到黑馬銀行!
歡迎第1位快速客戶來到黑馬銀行!
歡迎第4位普通客戶來到黑馬銀行!
歡迎第5位普通客戶來到黑馬銀行!
歡迎第6位普通客戶來到黑馬銀行!
歡迎第1位VIP客戶來到黑馬銀行!
歡迎第7位普通客戶來到黑馬銀行!
歡迎第8位普通客戶來到黑馬銀行!
請1號普通客戶到1號普通視窗辦理業務!1號普通視窗開始為1號普通客戶辦理業務。
請2號普通客戶到2號普通視窗辦理業務!2號普通視窗開始為2號普通客戶辦理業務。
請3號普通客戶到4號普通視窗辦理業務!4號普通視窗開始為3號普通客戶辦理業務。
請4號普通客戶到3號普通視窗辦理業務!3號普通視窗開始為4號普通客戶辦理業務。
請1號VIP客戶到1號VIP視窗辦理業務!1號VIP視窗開始為1號VIP客戶辦理業務。
請1號快速客戶到1號快速視窗辦理業務!1號快速視窗開始為1號快速客戶辦理業務。
歡迎第9位普通客戶來到黑馬銀行!
歡迎第10位普通客戶來到黑馬銀行!
歡迎第2位快速客戶來到黑馬銀行!
1號快速客戶在1號快速視窗辦理完業務啦!用時:3.0秒
業務辦理完成休息5秒!
4號普通客戶在3號普通視窗辦理完業務啦!用時:3.887秒
業務辦理完成休息5秒!
歡迎第3位快速客戶來到黑馬銀行!
3號普通客戶在4號普通視窗辦理完業務啦!用時:4.80秒
業務辦理完成休息5秒!
歡迎第2位VIP客戶來到黑馬銀行!
歡迎第11位普通客戶來到黑馬銀行!
1號普通客戶在1號普通視窗辦理完業務啦!用時:6.900秒
業務辦理完成休息5秒!
歡迎第12位普通客戶來到黑馬銀行!
1號VIP客戶在1號VIP視窗辦理完業務啦!用時:7.424秒
業務辦理完成休息5秒!
歡迎第4位快速客戶來到黑馬銀行!
請2號快速客戶到1號快速視窗辦理業務!1號快速視窗開始為2號快速客戶辦理業務。
請5號普通客戶到3號普通視窗辦理業務!3號普通視窗開始為5號普通客戶辦理業務。
歡迎第5位快速客戶來到黑馬銀行!
請6號普通客戶到4號普通視窗辦理業務!4號普通視窗開始為6號普通客戶辦理業務。
2號普通客戶在2號普通視窗辦理完業務啦!用時:9.396秒
業務辦理完成休息5秒!
歡迎第3位VIP客戶來到黑馬銀行!
歡迎第6位快速客戶來到黑馬銀行!
2號快速客戶在1號快速視窗辦理完業務啦!用時:3.0秒
業務辦理完成休息5秒!
請7號普通客戶到1號普通視窗辦理業務!1號普通視窗開始為7號普通客戶辦理業務。
歡迎第7位快速客戶來到黑馬銀行!
請2號VIP客戶到1號VIP視窗辦理業務!1號VIP視窗開始為2號VIP客戶辦理業務。
5號普通客戶在3號普通視窗辦理完業務啦!用時:3.999秒
業務辦理完成休息5秒!
歡迎第13位普通客戶來到黑馬銀行!
歡迎第4位VIP客戶來到黑馬銀行!
請8號普通客戶到2號普通視窗辦理業務!2號普通視窗開始為8號普通客戶辦理業務。
歡迎第5位VIP客戶來到黑馬銀行!
歡迎第14位普通客戶來到黑馬銀行!
請3號快速客戶到1號快速視窗辦理業務!1號快速視窗開始為3號快速客戶辦理業務。
2號VIP客戶在1號VIP視窗辦理完業務啦!用時:4.398秒
業務辦理完成休息5秒!
歡迎第15位普通客戶來到黑馬銀行!
6號普通客戶在4號普通視窗辦理完業務啦!用時:8.402秒
業務辦理完成休息5秒!
請9號普通客戶到3號普通視窗辦理業務!3號普通視窗開始為9號普通客戶辦理業務。
歡迎第8位快速客戶來到黑馬銀行!
8號普通客戶在2號普通視窗辦理完業務啦!用時:3.836秒
業務辦理完成休息5秒!
歡迎第16位普通客戶來到黑馬銀行!
3號快速客戶在1號快速視窗辦理完業務啦!用時:3.0秒
業務辦理完成休息5秒!
7號普通客戶在1號普通視窗辦理完業務啦!用時:7.140秒
業務辦理完成休息5秒!
歡迎第17位普通客戶來到黑馬銀行!
歡迎第18位普通客戶來到黑馬銀行!
請3號VIP客戶到1號VIP視窗辦理業務!1號VIP視窗開始為3號VIP客戶辦理業務。
歡迎第19位普通客戶來到黑馬銀行!
請10號普通客戶到4號普通視窗辦理業務!4號普通視窗開始為10號普通客戶辦理業務。
歡迎第6位VIP客戶來到黑馬銀行!
請11號普通客戶到2號普通視窗辦理業務!2號普通視窗開始為11號普通客戶辦理業務。
歡迎第20位普通客戶來到黑馬銀行!
請4號快速客戶到1號快速視窗辦理業務!1號快速視窗開始為4號快速客戶辦理業務。
請12號普通客戶到1號普通視窗辦理業務!1號普通視窗開始為12號普通客戶辦理業務。