题目如下:
/*
模拟实现银行业务调度系统逻辑,具体需求如下:
银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。
有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。
异步随机生成各种类型的客户,生成各类型用户的概率比例为:
VIP客户:普通客户:快速客户 = 1 :6 :3。
客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需的时间,快速客户办理业务所需时间为最小值(提示:办理业务的过程可通过线程Sleep的方式模拟)。
各类型客户在其对应窗口按顺序依次办理业务。
当VIP(6号)窗口和快速业务(5号)窗口没有客户等待办理业务的时候,这两个窗口可以处理普通客户的业务,而一旦有对应的客户等待办理业务的时候,则优先处理对应客户的业务。
随机生成客户时间间隔以及业务办理时间最大值和最小值自定,可以设置。
不要求实现GUI,只考虑系统逻辑实现,可通过打印的方式展现程序运行结果。
*/
方案一:
这个问题的解决借鉴了Java编程思想里面关于银行出纳仿真的小节,主要是直接使用了线程安全的容器ArrayBlockingQueue。代码如下:
Customer.java 本源文件定义了三种客户,以及枚举类型的客户类型。
package banktellersimulation;
enum CUSTOMER{
VIP, //1
ORDINARY, //6
QUICK //3
}
public class Customer {
private final CUSTOMER id;
private final int servicetime;
public Customer(CUSTOMER customer){
if (customer == CUSTOMER.VIP){
servicetime = 500;
} else if (customer == CUSTOMER.ORDINARY){
servicetime = 300;
} else {
servicetime = 100;
}
id = customer;
}
public int getServiceTime(){
return servicetime;
}
public String toString(){
return id.toString() + ":" + getServiceTime();
}
}
CustomerGenerator.java是一个生产者模型,即向相应的容器中添加客户——消费者。
package banktellersimulation;
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import com.sun.org.apache.xalan.internal.xsltc.compiler.sym;
public class CustomerGenerator implements Runnable{
private ArrayBlockingQueue<Customer> customerlinevip;
private ArrayBlockingQueue<Customer> customerlineoridinary;
private ArrayBlockingQueue<Customer> customerlinequick;
private Random rand = new Random();
private double[] data = new double[]{0.0, 0.1, 0.7, 1.0};
public CustomerGenerator(ArrayBlockingQueue<Customer> customerlinevip,
ArrayBlockingQueue<Customer> customerlineoridinary,
ArrayBlockingQueue<Customer> customerlinequick) {
super();
this.customerlinevip = customerlinevip;
this.customerlineoridinary = customerlineoridinary;
this.customerlinequick = customerlinequick;
}
@Override
public void run() {
while(!Thread.interrupted()){
int i = 0;
double temp = rand.nextDouble();
for (i = 0; i < data.length - 1; i++){
if (temp >= data[i]
&& temp < data[i + 1]){
break;
}
}
switch (CUSTOMER.values()[i]){
case VIP:
try {
customerlinevip.put(new Customer(CUSTOMER.VIP));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
case ORDINARY:
try {
customerlineoridinary.put(new Customer(CUSTOMER.ORDINARY));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
case QUICK:
try {
customerlinequick.put(new Customer(CUSTOMER.QUICK));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
default:
}
}
}
}
Window.java模拟银行的窗口类
package banktellersimulation;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
public class Window implements Runnable{
private final int id;
private ArrayBlockingQueue<Customer> customerlinevip;
private ArrayBlockingQueue<Customer> customerlineoridinary;
private ArrayBlockingQueue<Customer> customerlinequick;
public Window(int id, ArrayBlockingQueue<Customer> customerlinevip,
ArrayBlockingQueue<Customer> customerlineoridinary,
ArrayBlockingQueue<Customer> customerlinequick){
this.customerlinevip = customerlinevip;
this.customerlineoridinary = customerlineoridinary;
this.customerlinequick = customerlinequick;
this.id = id;
}
@Override
public void run() {
try{
while (!Thread.interrupted()){
Customer temp = null;
if (id >= 1 && id <= 4){
temp = customerlineoridinary.take();
TimeUnit.MICROSECONDS.sleep(temp.getServiceTime());
} else if (id == 5){
if (customerlinequick.size() == 0 && customerlineoridinary.size() != 0){
temp = customerlineoridinary.take();
TimeUnit.MICROSECONDS.sleep(temp.getServiceTime());
} else {
temp = customerlinequick.take();
TimeUnit.MICROSECONDS.sleep(temp.getServiceTime());
}
} else if (id == 6){
if (customerlinevip.size() == 0 && customerlineoridinary.size() != 0){
temp = customerlineoridinary.take();
TimeUnit.MICROSECONDS.sleep(temp.getServiceTime());
} else {
temp = customerlinevip.take();
TimeUnit.MICROSECONDS.sleep(temp.getServiceTime());
}
}
System.out.println(temp + "deal by:" + this);
}
}catch (InterruptedException e) {
e.printStackTrace();
}
}
public String toString(){
return id + "";
}
}
Bank.java测试类,线程运行的主函数
package banktellersimulation;
import java.util.concurrent.ArrayBlockingQueue;
public class Bank {
public static void main(String[] args){
ArrayBlockingQueue<Customer> customerlinevip = new ArrayBlockingQueue<Customer>(20);
ArrayBlockingQueue<Customer> customerlineoridinary = new ArrayBlockingQueue<Customer>(20);
ArrayBlockingQueue<Customer> customerlinequick = new ArrayBlockingQueue<Customer>(20);
new Thread(new CustomerGenerator(customerlinevip, customerlineoridinary, customerlinequick)).start();
for (int i = 1; i <=6 ;i++){
new Thread(new Window(i, customerlinevip, customerlineoridinary, customerlinequick)).start();
}
}
}
方案二:模拟银行的行为,下边的代码不是本人编写,但是编写的确高,特列写如下:
Constants.java,这个源文件里面定义了一些常量,主要是模拟服务时间的长短设置
package com.hzgg.demo;
public class Constants {
//服务的最小时间
public static final int MIN_SERVICE_TIME = 1000;
//服务的最大时间
public static final int MAX_SERVICE_TIME = 10000;
}
CustomerType.java,定义客户的类型(枚举)
package com.hzgg.demo;
public enum CustomerType {
COMMON, EXPRESS, VIP;
public String toString() {
switch (this) {
case COMMON:
return "普通";
case EXPRESS:
return "快速";
case VIP:
return "VIP";
}
return null;
}
}
NumberManager.java号码管理器
package com.hzgg.demo;
import java.util.ArrayList;
import java.util.List;
/*
* 号码管理器
*/
public class NumberManager {
private Integer nextNumber = 1;
private List<Integer> numberQueue = new ArrayList<Integer>();
/*
* 获取下一个号码
*/
public synchronized Integer getGenerateNewNumber() {
numberQueue.add(nextNumber);
return nextNumber++;
}
/*
* 叫号/获取下一个服务号
*/
public synchronized Integer fetchServiceNumber(){
Integer number = null;
if(numberQueue.size() > 0){
number = numberQueue.remove(0);
}
return number;
}
}
NumberMachine.java 取号机
package com.hzgg.demo;
/*
* 取号机
*/
public class NumberMachine {
private NumberManager commonManager = new NumberManager(); //普通号码生成器
private NumberManager expressManager = new NumberManager(); //快速号码生成器
private NumberManager vipManager = new NumberManager(); //VIP号码生成器
private static NumberMachine instance = new NumberMachine();
private NumberMachine() {
}
public static NumberMachine getInstance() {
return instance;
}
/*
* 取普通客户号码管理器
*/
public NumberManager getCommonManager() {
return commonManager;
}
/*
* 取快速客户号码管理器
*/
public NumberManager getExpressManager() {
return expressManager;
}
/*
* 取VIP客户号码管理器
*/
public NumberManager getVipManager() {
return vipManager;
}
}
CustomerManager.java客户生成器,生产者
package com.hzgg.demo;
/*
* 客户生成管理器
*/
public class CustomerManager extends Thread {
private NumberMachine numberMachine;
private NumberManager commonManager;
private NumberManager expressManager;
private NumberManager vipManager;
private CustomerType type;
private long time;
public CustomerManager(CustomerType type, long time) {
this.type = type;
this.time = time;
numberMachine = NumberMachine.getInstance();
commonManager = numberMachine.getCommonManager();
expressManager = numberMachine.getExpressManager();
vipManager = numberMachine.getVipManager();
}
public void run() {
while (true) {
Integer number = null;
switch (type) {
case COMMON:
number = commonManager.getGenerateNewNumber();
System.out.println(number + "号普通客户等待服务");
break;
case EXPRESS:
number = expressManager.getGenerateNewNumber();
System.out.println(number + "号快速客户等待服务");
break;
case VIP:
number = vipManager.getGenerateNewNumber();
System.out.println(number + "号VIP客户等待服务");
break;
default:
}
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
ServiceWindow.java服务窗口
package com.hzgg.demo;
import java.util.Random;
/*
* 服务窗口
*/
public class ServiceWindow extends Thread {
private NumberMachine numberMachine;
private NumberManager commonManager;
private NumberManager expressManager;
private NumberManager vipManager;
private Random rn = new Random();
private int windowId; // 窗口号
private CustomerType type = CustomerType.COMMON;
public ServiceWindow() {
numberMachine = NumberMachine.getInstance();
commonManager = numberMachine.getCommonManager();
expressManager = numberMachine.getExpressManager();
vipManager = numberMachine.getVipManager();
}
/*
* 窗口开始服务
*/
public void run() {
while (true) {
switch (type) {
case COMMON:
commonService();
break;
case EXPRESS:
expressService();
break;
case VIP:
vipService();
break;
default:
}
}
}
/*
* 普通客户服务
*/
private void commonService() {
System.out.println("第" + windowId + "号" + type + "窗口开始普通服务");
// 开始获取服务号
Integer number = commonManager.fetchServiceNumber();
if (number != null) {
// 开始服务
System.out.println("第" + windowId + "号" + type + "窗口正在为" + number
+ "号普通客户服务");
long beginTime = System.currentTimeMillis();// 服务开始时间
int maxRand = Constants.MAX_SERVICE_TIME
- Constants.MIN_SERVICE_TIME;
long serviceTime = rn.nextInt(maxRand) + Constants.MIN_SERVICE_TIME; // 服务时间
try {
Thread.sleep(serviceTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis(); // 服务结束时间
long costTime = endTime - beginTime;// 服务所花时间
System.out.println("第" + windowId + "号" + type + "窗口为" + number
+ "号普通客户服务完成,所花时间为" + costTime / 1000);
} else {
// 没有客户,等待
System.out.println("第" + windowId + "号" + type + "窗口没有客户,休息1秒");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/*
* 快速客户服务
*/
private void expressService() {
System.out.println("第" + windowId + "号" + type + "窗口开始服务");
Integer number = expressManager.fetchServiceNumber();
if (number != null) {
// 开始服务
System.out.println("第" + windowId + "号" + type + "窗口正在为" + number
+ "号快速客户服务");
try {
Thread.sleep(Constants.MIN_SERVICE_TIME);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("服务所花时间为" + Constants.MIN_SERVICE_TIME / 1000);
} else {
// 没有客户,处理普通用户
commonService();
}
}
/*
* VIP客户服务
*/
private void vipService() {
System.out.println("第" + windowId + "号" + type + "窗口开始服务");
// 开始获取服务号
Integer number = vipManager.fetchServiceNumber();
if (number != null) {
// 开始服务
System.out.println("第" + windowId + "号" + type + "窗口正在为" + number
+ "号VIP客户服务");
long beginTime = System.currentTimeMillis();// 服务开始时间
int maxRand = Constants.MAX_SERVICE_TIME
- Constants.MIN_SERVICE_TIME;
long serviceTime = rn.nextInt(maxRand) + Constants.MIN_SERVICE_TIME; // 服务时间
try {
Thread.sleep(serviceTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis(); // 服务结束时间
long costTime = endTime - beginTime;// 服务所花时间
System.out.println("服务所花时间为" + costTime / 1000);
} else {
// 没有客户,处理普通用户
commonService();
}
}
public void setType(CustomerType type) {
this.type = type;
}
public void setWindowId(int windowId) {
this.windowId = windowId;
}
}
MainClass.java 测试类
package com.hzgg.demo;
public class MainClass {
public static void main(String[] args) {
//4个普通窗口
for(int i=1;i<5;i++){
ServiceWindow commWin = new ServiceWindow();
commWin.setWindowId(i);
commWin.start();
}
//1个快速窗口
ServiceWindow expWin = new ServiceWindow();
expWin.setType(CustomerType.EXPRESS);
expWin.setWindowId(5);
expWin.start();
//1个VIP窗口
ServiceWindow vipWin = new ServiceWindow();
vipWin.setType(CustomerType.VIP);
vipWin.setWindowId(6);
vipWin.start();
//生成客户
CustomerManager commonCustomer = new CustomerManager(CustomerType.COMMON, 1000); //1秒种生成一个
commonCustomer.start();
CustomerManager expressCustomer = new CustomerManager(CustomerType.EXPRESS, 2000); //2秒种生成一个
expressCustomer.start();
CustomerManager vipCustomer = new CustomerManager(CustomerType.VIP, 6000); //6秒种生成一个
vipCustomer.start();
}
}
代码纯粹个人编写(方案一),水平有限如果有什么错误,欢迎大家扶正。