---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流!----------------------
模拟实现银行业务调度系统逻辑,具体需求如下:
银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIp窗口。
有三种对应类型的客户:VIp客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。
异步随机生成各种类型的客户,生成各类型用户的概率比例为:
VIp客户 :普通客户 :快速客户 = 1 :6 :3。
客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIp客户以及普通客户办理业务所需的时间,快速客户办理业务所需时间为最小值
(提示:办理业务的过程可通过线程Sleep的方式模拟)
各类型客户在其对应窗口按顺序依次办理业务。
当VIp(6号)窗口和快速业务(5号)窗口没有客户等待办理业务的时候,这两个窗口可以处理普通客户的业务,而一旦有对应的客户等待办理业务的时候,则优先处理对应客户的业务。
随机生成客户时间间隔以及业务办理时间最大值和最小值自定,可以设置。
不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。
1、面向对象分析与设计
有三种对应类型的客户:VIP客户,普通客户,快速客户 ,异步随机生成各种类型的客户,各类型客户在其对应窗口按顺序依次办理业务 。
首先,经常在银行办理业务的人更有利于理解本系统,我们知道每一个客户其实就是由银行的一个取号机器产生号码的方式来表示的。所以,要有一个号码管理器对象,让这个对象不断地产生号码,就等于随机生成了客户。
由于有三类客户,每类客户的号码编排都是完全独立的,所以,本系统一共要产生三个号码管理器对象,各自管理一类用户的排队号码。
这三个号码管理器对象统一由一个号码机器进行管理,这个号码机器在整个系统中始终只能有一个,所以,它要被设计成单例。
各类型客户在其对应窗口按顺序依次办理业务 ,准确地说,应该是窗口依次叫号。
各个窗口怎么知道该叫哪一个号了呢?它一定是问的相应的号码管理器,即服务窗口每次找号码管理器获取当前要被服务的号码。
2、根据以上分析,类图设计如下:
下面开始编写代码:
1.创建用户服务窗口
package com.csdn.interview.bank;
public class CreateWindow {
public void getWindow() {
//创建五个普通用户窗口
for (int i = 1; i < 5; i++) {
ServiceWindow commonServiceWindow = new ServiceWindow();// 创建普通服务窗口
commonServiceWindow.setWindowID(i);// 给服务窗口编号
commonServiceWindow.startGetNumber();// 服务窗口开始获取任务
}
ServiceWindow speedServiceWindow = new ServiceWindow();// 创建快速服务窗口
speedServiceWindow.setClientType(ClientType.SpeedClient);// 给快速窗口设置服务客户类型
speedServiceWindow.startGetNumber();
ServiceWindow vipServiceWindow = new ServiceWindow();// 创建VIP服务窗口
vipServiceWindow.setClientType(ClientType.VipClient);
vipServiceWindow.startGetNumber();
}
}
2.创建客户类型
package com.csdn.interview.bank;
public enum ClientType {
CommonClient,SpeedClient,VipClient;
public String toString()
{
//this代表当前类的 clienttype
switch (this) {
case CommonClient:
return “普通客户”;
case SpeedClient:
return “快速客户”;
case VipClient:
return name();//返回当前类型
}
return null;
}
}
3.创建客户
package com.csdn.interview.bank;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class CreateClient {
private static final int timer = 1;// 每一秒钟产生一个普通客户
public void getClient(){
//普通客户
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
public void run() {
Integer number=GetNumberMachine.getInstance().getCommonClient().clientGetNumber();//普通客户开始取号、
System.out.println("第"+number+"号普通客户正在等待服务");
}
}, 0, 1, TimeUnit.SECONDS);
//快速客户
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
public void run() {
Integer number=GetNumberMachine.getInstance().getSpeedClient().clientGetNumber();//普通客户开始取号、
System.out.println("第"+number+"号快速客户正在等待服务");
}
}, 0, timer * 6, TimeUnit.SECONDS);
//VIP客户
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
public void run() {
Integer number=GetNumberMachine.getInstance().getVipClient().clientGetNumber();//普通客户开始取号、
System.out.println("第"+number+"号VIP客户正在等待服务");
}
}, 0,timer*12, TimeUnit.SECONDS);
}
4.创建银行取号机器
package com.csdn.interview.bank;
public class GetNumberMachine {
private NumberManager commonClient = new NumberManager();//普通客户服务窗口
private NumberManager speedClient = new NumberManager();//快速窗口
private NumberManager vipClient = new NumberManager();//vip窗口
public NumberManager getCommonClient() {
return commonClient;
}
public void setCommonClient(NumberManager commonClient) {
this.commonClient = commonClient;
}
public NumberManager getSpeedClient() {
return speedClient;
}
public void setSpeedClient(NumberManager speedClient) {
this.speedClient = speedClient;
}
public NumberManager getVipClient() {
return vipClient;
}
public void setVipClient(NumberManager vipClient) {
this.vipClient = vipClient;
}
private GetNumberMachine(){
}
//这是单列设计模式,构造方法是私有的的,就要用静态,返回一取号机实例,也就是一个号码管理器
public static GetNumberMachine getInstance()
{
return machine;
}
private static GetNumberMachine machine=new GetNumberMachine();//私有的构造方法就自己创建一个取号机,供别人使用
}
5.号码管理器
package com.csdn.interview.bank;
import java.util.ArrayList;
import java.util.List;
public class NumberManager {
private int number=1;
private List<Integer> sequenceNumber=new ArrayList<Integer>();//创建一个客户存储服务号数组
//客户取号
public synchronized Integer clientGetNumber()
{
sequenceNumber.add(number);
return number++;
}
//服务窗口去服务号
public synchronized Integer windowGetServiceNumber()
{
if (sequenceNumber.size()>0) {
return sequenceNumber.remove(0);//窗口每次取号都从数组的第一个取号
}
return null;
}
}
6.服务窗口
package com.csdn.interview.bank;
import java.util.Random;
import java.util.concurrent.Executors;
public class ServiceWindow {
private ClientType clientType=ClientType.VipClient ;
private int windowID = 1;// 服务窗口默认号
public void setClientType(ClientType clientType) {
this.clientType = clientType;
}
public void setWindowID(int windowID) {
this.windowID = windowID;
}
// 服务窗口开始取号
public void startGetNumber() {
// 这就话就是取号窗口把任务分配给线程池,线程池在吧任务分配给某个线程
Executors.newSingleThreadExecutor().execute(new Runnable() {
public void run() {
while (true) {
switch (clientType) {
case CommonClient:
commonServiceWindow();
break;
case SpeedClient:
speedServiceWindow();
break;
case VipClient:
vipServiceWindow();
break;
}
}
}
});
}
//VIP服务窗口
private void vipServiceWindow() {
String winName="第" + windowID + "号"+ clientType + "窗口";
// 服务窗口通过取号机获取服务的客服号
Integer number = GetNumberMachine.getInstance().getVipClient().windowGetServiceNumber();
System.out.println(winName+"正在获取服务对象");
if (number != null) {
long begintime = System.currentTimeMillis();
try {
Thread.sleep((new Random().nextInt(10) + 1)*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long endtiem = System.currentTimeMillis();
System.out.println(winName+"为第" + number + "号"+ clientType + "服务" + (endtiem - begintime)/ 1000 + "秒");
} else {
System.out.println("没有要服务的vip客户");
commonServiceWindow();//如果vip窗口没有服务对象,就给普通客户服务
}
}
//快速服务窗口
private void speedServiceWindow() {
String winName="第" + windowID + "号"+clientType+"窗口";
// 服务窗口通过取号机获取服务的客服号
Integer number = GetNumberMachine.getInstance().getSpeedClient().windowGetServiceNumber();
System.out.println(winName+"正在获取服务对象");
if (number != null) {
long begintime = System.currentTimeMillis();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long endtiem = System.currentTimeMillis();
System.out.println(winName+"为第" + number + "号"+ clientType + "服务" + (endtiem - begintime)/ 1000 + "秒");
} else {
System.out.println("没有要服务的客户");
commonServiceWindow();//如果快速窗口没有服务对象,就给普通客户服务
}
}
//普通客户服务窗口
private void commonServiceWindow() {
String winName="第" + windowID + "号"+ clientType + "窗口";
// 服务窗口通过取号机获取服务的客服号
Integer number = GetNumberMachine.getInstance()
.getCommonClient().windowGetServiceNumber();
System.out.println(winName+"正在获取服务对象");
if (number != null) {
long begintime = System.currentTimeMillis();
try {
Thread.sleep(((new Random().nextInt(10)) + 1)*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long endtiem = System.currentTimeMillis();
System.out.println(winName+"为第" + number + "号"+ "普通客户"+ "服务" + (endtiem - begintime)/ 1000 + "秒");
} else {
System.out.println("没有你要服务的客户");
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
7.主程序,检验此程序是否能合格运行
package com.csdn.interview.bank;
public class Main {
public static void main(String[] args) {
//创建银行服务窗口
new CreateWindow().getWindow();
//创建客户
new CreateClient().getClient();
}
}
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流!----------------------