多线程模拟银行业务办理
PS.强烈建议使用线程池来做,个人估计可以比下面的代码少一半。
项目介绍
设计一个多线程模拟银行业务办理程序:
(1)业务时间
模拟客户可以随机办理银行提供的8种业务中的一种(基准时间自定义),办理时间规划为:
业务 | 业务序号 | 办理时间范围 |
---|---|---|
取款 | 1 | 0.5* 基准时间-1.5* 基准时间 |
存款 | 2 | 0.5* 基准时间-1.5* 基准时间 |
缴纳罚款 | 3 | 1.2* 基准时间-2.0* 基准时间 |
开通网银 | 4 | 5.0* 基准时间-8.0* 基准时间 |
缴纳水电费 | 5 | 1.5* 基准时间-2.0* 基准时间 |
购买基金 | 6 | 2.0* 基准时间-3.0* 基准时间 |
转账汇款 | 7 | 3.0* 基准时间-4.0* 基准时间 |
个贷还款 | 8 | 2.0* 基准时间-4.0* 基准时间 |
(2)服务窗口
程序模拟多个窗口服务,窗口服务具有一定的差异化,窗口开放情况:
业务 | 业务序号 | 办理时间范围 |
---|---|---|
A 类窗口 |
1,2,3,4,5,6,7,8 |
所有客户 |
B 类窗口 |
1,2,4,5,7 |
所有客户 |
C 类窗口 |
1,2,3,4,5,6,7,8 |
VIP优先 |
(3)模拟客户
客户区分普通
客户与VIP
客户
客户模拟需随机产生
(4)展示客户列表
模拟时间:8:00-17:00
结束营业后,打印当天客户列表
客户列表包含:客户名称
、客户到达时间
、客户办理业务类型
、客户所用时间
(5)统计数据
当天客户平均业务办理时间
当天客户所有办理业务中的所占比例
(6)仿真性要求
参数化设定当天客户办理业务的比例(比如设置业务1占20%)
提供窗口开放建议:根据当日的业务情况给出建议的A、B、V
类三窗口数量,达到与基准日一致的客户服务时间
考核要求
(1)提交规范的代码
(2)系统包含多线程
、线程互斥
、线程同步
(3)业务类型使用Enum类型
(4)程序所有存储都需要使用集合
,不能使用数组
(1)程序整体结构设计
(2)包含有营业过程管理:开门
、关门
、营业分配过程
(3)实现用户模拟
(4)实现窗口分配模拟
(5)仿真的方法(设计仿真的方法)
(1)上交完整工程代码
(2)相关说明文档
主要功能
类职责划分
UML图
描述
- Bank,负责执行题目要求的计算逻辑。
- Utils,一些工具函数,例如取随机数或者打印数据。
- DateGenerator,随机数据的生成类。
- BankExecutor,核心代码,业务模拟执行、调度的核心。
- ServiceWindow:BankExecutor的内部类,表示服务窗口。
- User:用户类 。
- BusinessEnum:业务类型枚举类。
- ServiceWindowEnum: 服务窗口枚举类。
核心代码
bank.java
package com.yzl;
/**
* 银行
*
*/
public class Bank {
public static final int TOTAL_WINDOWS = 4;
public static void main(String[] args) throws InterruptedException {
// 测试基准日
double res = doBasicDayTest();
System.out.println("基准日平均办理时间:" + res + "s");
// 寻找和基准日最相近的窗口
getBestWindowCondition();
}
/**
* 传入窗口总数,模拟当日活动
*
* @param a a窗口数目
* @param b b窗口数目
* @param v v窗口数目
* @param business 业务比例(1个或者多个)
*/
public static Double doDayTest(Integer a, Integer b, Integer v, Double... business) throws InterruptedException {
BankExecutor bankExecutor = new BankExecutor();
System.out.printf("%-15s %-15s %-15s %-15s %-15s %-15s\n", "窗口", "用户", "是否VIP", "业务", "本次服务时间", "用户到达时间");
DataGenerator dataGenerator = new DataGenerator(bankExecutor);
dataGenerator.generateUsers(business);
dataGenerator.generateSampleWindow(a, b, v);
// 等待银行“关门”
Thread.sleep(1000);
// 设置关门状态
bankExecutor.shutDownBank();
// 执行到此,所有窗口都已完成关闭(shutDownBank会阻塞),我们遍历所有窗口来查看状态
return Utils.showWindowCondition(bankExecutor);
}
/**
* 基准日
*/
public static Double doBasicDayTest() throws InterruptedException {
return doDayTest(1, 2, 1, 0.2, 0.2, 0.1, 0.1, 0.05, 0.15, 0.10, 0.10);
}
/**
* 获取最佳窗口开放情况
*/
public static void getBestWindowCondition() throws InterruptedException {
// 基准日
double res = doBasicDayTest();
double minTimeDelta = Integer.MAX_VALUE;
double minTime = Integer.MAX_VALUE;
int oa = 1;
int ob = 2;
int ov = 1;
// 排列组合,我们的总窗口数不变
for (int i = 0; i <= TOTAL_WINDOWS; i++) {
for (int j = 0; j <= TOTAL_WINDOWS - i; j++) {
int k = TOTAL_WINDOWS - i - j;
// 排除基准日
if (i == 1 && j == 2 && k == 1) {
continue;
}
System.out.println("测试:" + i + "A " + j + "B " + k + "V");
double tmp = doDayTest(i, j, k, 0.1, 0.1, 0.05, 0.05, 0.05, 0.4, 0.05, 0.2);
if (Math.abs(tmp - res) < minTimeDelta) {
minTimeDelta = Math.abs(tmp - res);
minTime = tmp;
oa = i;
ob = j;
ov = k;
}
}
}
System.out.println("和基准日基本一致的窗口开发情况:");
System.out.println("A窗口" + oa);
System.out.println("B窗口" + ob);
System.out.println("V窗口" + ov);
System.out.println