银行系统面试题总结
该系统中主要有四个对象:客户类型,号码机,号码出口,服务窗口。
设计思路:当有客户进来银行办理业务时,根据客户类型(是普通客户还是快速客户还是VIP客户)从号码机中相应的号码出口中生产出相应的号码交给客户,服务窗口叫号为客户服务。
1.创建一个客户类型类,用枚举表示。
publicenum CustomerType {
Common, Express,VIP;
}
2.创建一个号码机类,使用单例设计模式获取一个号码机。该类中包含三个号码出口成员变量,分别是commonServiceNumberExit,expressServiceNumberExit,VIPServiceNumberExit。
publicclass NumberMachine {
//号码机中有三个号码出口,分别是普通服务出口,快速服务出口,VIP服务出口
private NumberExits commonServiceNumberExit = new NumberExits();
private NumberExits expressServiceNumberExit= new NumberExits();
private NumberExits VIPServiceNumberExit = new NumberExits();
//获取普通服务出口
public NumberExits getCommonServiceNumberExit() {
returncommonServiceNumberExit;
}
//获取快速服务出口
public NumberExits getExpressServiceNumberExit() {
returnexpressServiceNumberExit;
}
//获取VIP服务出口
public NumberExits getVIPServiceNumberExit() {
returnVIPServiceNumberExit;
}
publicstatic NumberMachine getNumberMachine() {
returnnumberMachine;
}
//使用饿汉式的单例模式,获取一个号码机
privatestatic NumberMachine numberMachine=new NumberMachine();
private NumberMachine(){
}
publicstatic NumberMachine getInstance(){
returnnumberMachine;
}
}
3.创建一个号码出口类,该类中号码成员变量,以及存取号码的集合成员变量。并且该类封装了产生号码和分配号码的方法。这两个方法都是同步的。
import java.util.ArrayList;
import java.util.List;
public class NumberExits {
//号码从1开始
private int lastNumber=1;
//创建一个集合queue用来存号码
List<Integer> queueList = new ArrayList<Integer>();
//产生一个服务号码,并把号码存入queueList集合中
public synchronized Integer generateNewServiceNumber(){
queueList.add(lastNumber);
return lastNumber++;
}
//分配产生出来的号码给客户
public synchronized Integer distributingNumber(){
Integer number = null;
if(queueList.size()>0)
return number=queueList.remove(0);
else
return number;
}
}
4.创建一个服务窗口类,该类中封装了叫号服务的方法,该方法根据客户的类型调用相应的窗口为其服务。
import java.util.Random;
import java.util.concurrent.Executors;
public class ServiceWindow {
//默认窗口号为1
private int windowId=1;
//默认客户类型为普通客户
private CustomerType customerType=CustomerType.Common;
//设置窗口号
public void setWindowId(int windowId) {
this.windowId = windowId;
}
//设置客户类型
public void setcustomerType(CustomerType customerType){
this.customerType = customerType;
}
//根据相应的客户类型调用的服务方法
public void windowCallingNumber(){
Executors.newSingleThreadExecutor().execute(new Runnable(){
public void run(){
while(true){
//普通客户,
if(customerType==CustomerType.Common){
commonService();
}else if(customerType==CustomerType.Express){
expressService();
}else
VIPService();
}
}
//从号码机中获得一个普通客户号码,如果号码不为空,就为持有该号码的客户服务并打印出服务时间
//号码为空时,就让窗口休息5秒
private void commonService() {
String windowName ="第"+ windowId +"号普通窗口";
System.out.println(windowName+"正在获取任务");
//从号码机中获得一个普通号
Integer number= NumberMachine.getInstance().getCommonServiceNumberExit().distributingNumber();
if(number!=null){
System.out.println(windowName + "正在为第"+ number +"个普通客户服务");
//服务的开始时间
long beginTime = System.currentTimeMillis();
//初始化服务时间
long serverTime =0;
try {
//最大的随机值
int maxrandValue=Constants.MaxServingTime-Constants.MinServingTime;
//线程随机睡眠
Thread.sleep(new Random().nextInt(maxrandValue)+1+Constants.MinServingTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
//服务一个客户花费的时间
long costTime = endTime-beginTime;
System.out.println(windowName + "为第"+ number +"个普通客户完成服务,耗时"+ costTime/1000+"秒");
}else
System.out.println("没有任务,休息一下");
try {
//没有客户服务,就休息5秒
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//从号码机中获得一个快速客户号码,如果号码不为空 ,就为持有该号码的客户服务并打印出服务时间
//号码为空时,就去帮普通客户窗口
private void expressService() {
String windowName ="第"+windowId+"号快速窗口";
System.out.println(windowName+"正在获取任务");
Integer number= NumberMachine.getInstance().getExpressServiceNumberExit().distributingNumber();
if(number!=null){
System.out.println(windowName + "正在为第"+ number +"个快速客户服务");
long beginTime = System.currentTimeMillis();
try {
Thread.sleep(Constants.MinServingTime);
//service();
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
long costTime = endTime-beginTime;
System.out.println(windowName + "为第"+ number +"个快速户完成服务,耗时"+ costTime/1000+"秒");
}else
System.out.println(windowName+"没有任务,去帮普通窗口");
commonService();
}
//从号码机中获得一个VIP客户号码,如果号码不为空 ,就为持有该号码的客户服务并打印出服务时间
//号码为空时,就去帮普通客户窗口
private void VIPService() {
String windowName ="第"+windowId+"号VIP窗口";
System.out.println(windowName+"正在获取任务");
Integer number= NumberMachine.getInstance().getVIPServiceNumberExit().distributingNumber();
if(number!=null){
System.out.println(windowName + "正在为第"+ number +"个VIP客户服务");
long beginTime = System.currentTimeMillis();
long serverTime =0;
try {
int maxrandValue=Constants.MaxServingTime-Constants.MinServingTime;
Thread.sleep(new Random().nextInt(maxrandValue)+1+Constants.MinServingTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
long costTime = endTime-beginTime;
System.out.println(windowName + "为第"+ number +"个VIP客户完成服务,耗时"+ costTime/1000+"秒");
}else
System.out.println(windowName+"没有任务,去帮忙普通窗口");
commonService();
}
});
}
}
5.编写一个main类来测试,该类会首先生成6个普通窗口和1个快速,1个VIP窗口。
通过三个线程模拟不同客户的到来情况:
第1秒钟的时候就会有1个普通客户来到银行,号码机为其创建一个普通服务号码,然后客户等待服务;每隔2秒钟,就会再来一个普通客户。
第8秒钟的时候就会有1个快速客户来到银行,号码机为其创建一个快速服务号码,然后客户等待服务;每隔12秒钟,就会再来一个快速客户。
第10秒钟的时候就会有1个VIP客户来到银行,号码机为其创建一个VIP服务号码,然后客户等待服务;每隔12秒钟,就会再来一个VIP客户。
各类客户被叫到号后到相应的服务窗口去办业务。
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args){
//创建6个普通窗口
for(int i=1; i<7; i++){
ServiceWindow commonWindow = new ServiceWindow();
commonWindow.setWindowId(i);
commonWindow.windowCallingNumber();
}
//创建一个快速服务窗口
ServiceWindow expressWindow = new ServiceWindow();
expressWindow.setcustomerType(CustomerType.Express);
expressWindow.windowCallingNumber();
//创建一个VIP服务窗口
ServiceWindow VIPWindow = new ServiceWindow();
VIPWindow.setcustomerType(CustomerType.VIP);
VIPWindow.windowCallingNumber();
//普通客户第一秒钟后就会来,然后每两秒钟会来一个。通过固定频率线程调度器
//为他们分配号码
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable(){
public void run(){
Integer number = NumberMachine.getInstance().getCommonServiceNumberExit().generateNewServiceNumber();
System.out.println(number+"号普通客户等待服务");
}
},
1,//第一秒钟开始来
2, //每两秒钟会再来一个
TimeUnit.SECONDS);//时间单位是秒
//快速客户第8秒钟后就会来,然后每12秒钟会来一个。通过固定频率线程调度器
//为他们分配号码
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable(){
public void run(){
Integer number = NumberMachine.getInstance().getExpressServiceNumberExit().generateNewServiceNumber();
System.out.println(number+"号快速客户等待服务");
}
},
8,
12,
TimeUnit.SECONDS);
//VIP客户第10秒钟后就会来,然后每6秒钟会来一个。通过固定频率线程调度器
//为他们分配号码
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable(){
public void run(){
Integer number = NumberMachine.getInstance().getVIPServiceNumberExit().generateNewServiceNumber();
System.out.println(number+"号VIP客户等待服务");
}
},
10,
6,
TimeUnit.SECONDS);
}
}