Java银行调度系统
具体需求如下:
- 有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。
异步随机生成各种类型的客户,生成各类型用户的概率比例为:
VIP客户:普通客户:快速客户 = 1 :6 :3。
客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需的时间,快速客户办理业务所需时间为最小值(提示:办理业务的过程可通过线程Sleep的方式模拟)。
当VIP窗口和快速业务窗口没有客户等待办理业务的时候,这两个窗口可以处理普通客户的业务,而一旦有对应的客户等待办理业务的时候,则优先处理对应客户的业务。
随机生成客户时间间隔以及业务办理时间最大值和最小值自定,可以设置。
面向对象的分析和设计:
- 每一个客户由银行的一个取号机器产生号码的方式来表示。所以,有一个号码管理器对象,让这个对象不断地产生号码,就等于随机生成了客户。
- 由于有三类客户,每类客户的号码编排都是完全独立的,所以一共要产生三个号码管理器对象,各自管理一类用户的排队号码。
- 这三个号码管理器对象统一由一个号码机器进行管理,这个号码机器在整个系统中始终只能有一个,所以它要被设计成单例。
- 各个窗口怎么知道该叫哪一个号了呢?它一定是问的相应的号码管理器,即服务窗口每次找号码管理器获取当前要被服务的号码。
类图:
类的编码实现
NumberManager类
- 定义一个用于存储上一个客户号码的成员变量和用于存储所有等待服务的客户号码的队列集合。
- 定义一个产生新号码的方法generateNewManager()和获取要为之服务的号码的方法fetchServiceNumber(),这两个方法被不同的线程操作了相同的数据,所以要进行同步。
代码如下:
package heimablog.bank; import java.util.ArrayList;
import java.util.List; public class NumberManager {
//定义一个用于存储上一个客户号码的成员变量
private int lastNumber = 0;
//定义一个用于存储所有等待服务的客户号码的队列集合
private List<Integer> queueNumbers = new ArrayList<Integer>(); //产生新号码
public synchronized Integer generateNewManager(){
queueNumbers.add(++lastNumber);
return lastNumber;
} //获取要服务的号码
public synchronized Integer fetchServiceNumber(){
if (queueNumbers.size() > 0) {
return queueNumbers.remove(0);
}else {
return null;
}
} /**
* 上面的2个方法被2个不同的线程访问相同的数据就会出现问题,所以要进行同步(synchronized)
*/
}
NumberMachine类
- 定义三个成员变量分别指向三个NumberManager对象,分别表示普通、快速和VIP客户的号码管理器,定义三个对应的方法来返回这三个NumberManager对象。
- 将NumberMachine类设计成单例。
代码如下:
package heimablog.bank; public class NumberMachine {
//定义三个成员变量分别指向三个NumberManager对象,分别表示普通、快速和VIP客户的号码管理器
private NumberManager commonManager = new NumberManager();
private NumberManager expressManager = new NumberManager();
private NumberManager vipManager = new NumberManager(); //定义三个对应的方法来返回这三个NumberManager对象
public NumberManager getCommonManager() {
return commonManager;
}
public NumberManager getExpressManager() {
return expressManager;
}
public NumberManager getVipManager() {
return vipManager;
} /**
* 分两步写,将普通对象变为单例:
* 先构造函数私有化,别人就无法创建实例了,这样人家就只有调用其静态方法
*/
private NumberMachine(){}
public static NumberMachine instance = new NumberMachine();
public static NumberMachine getInstance(){
return instance;
}
}
CustomerType枚举类
- 系统中有三种类型的客户,所以用定义一个枚举类,其中定义三个成员分别表示三种类型的客户。
- 重写toString方法,返回类型的中文名称。
代码如下:
package heimablog.bank; public enum CustomerTypes {
COMMON,EXPRESS,VIP; //重写toString方法,返回类型的中文名称
public String toString(){
String name = null;
switch (this) {
case COMMON:
name = "普通";
break;
case EXPRESS:
name = "快速";
break;
case VIP:
name = name();
break;
}
return name;
}
}
ServiceWindow类
- 定义一个start方法,内部启动一个线程,根据服务窗口的类别分别循环调用三个不同的方法。
- 定义三个方法分别对三种客户进行服务,为了观察运行效果,应详细打印出其中的细节信息。
代码如下:
package heimablog.bank; import java.util.Random;
import java.util.concurrent.Executors;
import java.util.logging.Logger; public class ServiceWindow {
private static Logger logger = Logger.getLogger("heimablog.bank");
private CustomerTypes type = CustomerTypes.COMMON;
private int windowId = 1; public CustomerTypes getType() {
return type;
}
public void setType(CustomerTypes type) {
this.type = type;
}
public void setWindowId(int windowId) {
this.windowId = windowId;
} public void start(){
Executors.newSingleThreadExecutor().execute(new Runnable() { @Override
public void run() {
while (true) {
switch (type) {
case COMMON:
commonService();
break;
case EXPRESS:
expressService();
break;
case VIP:
vipService();
break;
}
}
}
});
} private void commonService() {
String windowName = "第 " + windowId + " 号 " + type + " 窗口";
System.out.println(windowName + "开始获取 普通 任务-->");
Integer number = NumberMachine.getInstance().getCommonManager().fetchServiceNumber();
if (number != null) {
System.out.println(windowName + "开始为第" + number + "号" + "普通客户服务~~~");
long beginTime = System.currentTimeMillis();
int maxRand = Constants.MAX_SERVER_TIME - Constants.MIN_SERVER_TIME;
long serverTime = new Random().nextInt(maxRand) + 1 + Constants.MIN_SERVER_TIME;
try {
Thread.sleep(serverTime);
} 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 + "没有取到普通任务,正在空闲一秒!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} private void expressService() {
Integer number = NumberMachine.getInstance().getExpressManager().fetchServiceNumber();
String windowName = "第 " + windowId + " 号 " + type + " 窗口";
System.out.println(windowName + "开始获取快速任务--->");
if (number != null) {
System.out.println(windowName + "开始为第" + number + "号" + "快速客户服务~~~");
long beginTime = System.currentTimeMillis();
long serverTime = Constants.MIN_SERVER_TIME;
try {
Thread.sleep(serverTime);
} 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 + "没有获取到 express 任务,获取 common 任务!");
commonService();
}
} private void vipService() {
Integer number = NumberMachine.getInstance().getVipManager().fetchServiceNumber();
String windowName = "第 " + windowId + " 号 " + type + " 窗口";
System.out.println(windowName + "开始获取VIP任务--->");
if (number != null) {
System.out.println(windowName + "开始为第" + number + "个号" + "VIP客户服务~~~");
long beginTime = System.currentTimeMillis();
int maxRand = Constants.MAX_SERVER_TIME - Constants.MIN_SERVER_TIME;
long serverTime = new Random().nextInt(maxRand) + 1 + Constants.MIN_SERVER_TIME;
try {
Thread.sleep(serverTime);
} 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 + "没有获取到 VIP 任务,获取 common 任务!");
commonService();
}
}
}
MainClass类
- 用for循环创建出4个普通窗口,再创建出1个快速窗口和1个VIP窗口。
- 接着再创建三个定时器,分别定时去创建新的普通客户号码、新的快速客户号码、新的VIP客户号码。
代码如下:
package heimablog.bank; import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger; public class MainClass { private static Logger logger = Logger.getLogger("heimablog.bank"); public static void main(String[] args) {
//产生4个普通窗口
for (int i = 1; i < 5; i++) {
ServiceWindow commonWindow = new ServiceWindow();
commonWindow.setWindowId(i);
commonWindow.start();
} //产生1个快速窗口
ServiceWindow expressWindow = new ServiceWindow();
expressWindow.setType(CustomerTypes.EXPRESS);
expressWindow.start(); //产生1个VIP窗口
ServiceWindow vipWindow = new ServiceWindow();
vipWindow.setType(CustomerTypes.VIP);
vipWindow.start(); //普通客户拿号
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() { @Override
public void run() {
Integer number = NumberMachine.getInstance().getCommonManager().generateNewManager();
System.out.println(number + "号【普通客户】等待服务^_^");
}
}, 1, Constants.COMMON_CUSTOMER_INTERVAL_TIME, TimeUnit.SECONDS); //快速客户拿号
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() { @Override
public void run() {
Integer number = NumberMachine.getInstance().getExpressManager().generateNewManager();
System.out.println(number + "号【快速客户】等待服务^_^");
}
}, 1, Constants.COMMON_CUSTOMER_INTERVAL_TIME * 2, TimeUnit.SECONDS); //VIP客户拿号
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() { @Override
public void run() {
Integer number = NumberMachine.getInstance().getVipManager().generateNewManager();
System.out.println(number + "号【VIP客户】等待服务^_^");
}
}, 1, Constants.COMMON_CUSTOMER_INTERVAL_TIME * 6, TimeUnit.SECONDS); } }
Constants类
- 定义三个常量:MAX_SERVICE_TIME、MIN_SERVICE_TIME、COMMON_CUSTOMER_INTERVAL_TIME。
代码如下:
package heimablog.bank; public class Constants {
public static int MAX_SERVER_TIME = 10000;
public static int MIN_SERVER_TIME = 1000;
public static int COMMON_CUSTOMER_INTERVAL_TIME = 1;
}
执行结果如下:
第 1 号 普通 窗口开始获取 普通 任务-->
第 1 号 普通 窗口没有取到普通任务,正在空闲一秒!
第 3 号 普通 窗口开始获取 普通 任务-->
第 3 号 普通 窗口没有取到普通任务,正在空闲一秒!
第 1 号 快速 窗口开始获取快速任务--->
第 1 号 快速 窗口没有获取到 express 任务,获取 common 任务!
第 1 号 快速 窗口开始获取 普通 任务-->
第 1 号 快速 窗口没有取到普通任务,正在空闲一秒!
第 2 号 普通 窗口开始获取 普通 任务-->
第 2 号 普通 窗口没有取到普通任务,正在空闲一秒!
第 4 号 普通 窗口开始获取 普通 任务-->
第 4 号 普通 窗口没有取到普通任务,正在空闲一秒!
第 1 号 VIP 窗口开始获取VIP任务--->
第 1 号 VIP 窗口没有获取到 VIP 任务,获取 common 任务!
第 1 号 VIP 窗口开始获取 普通 任务-->
第 1 号 VIP 窗口没有取到普通任务,正在空闲一秒!
1号【普通客户】等待服务^_^
1号【快速客户】等待服务^_^
1号【VIP客户】等待服务^_^
2号【普通客户】等待服务^_^
第 1 号 普通 窗口开始获取 普通 任务-->
第 1 号 普通 窗口开始为第1号普通客户服务~~~
第 3 号 普通 窗口开始获取 普通 任务-->
第 3 号 普通 窗口开始为第2号普通客户服务~~~
第 1 号 快速 窗口开始获取快速任务--->
第 1 号 快速 窗口开始为第1号快速客户服务~~~
第 2 号 普通 窗口开始获取 普通 任务-->
第 2 号 普通 窗口没有取到普通任务,正在空闲一秒!
第 4 号 普通 窗口开始获取 普通 任务-->
第 4 号 普通 窗口没有取到普通任务,正在空闲一秒!
第 1 号 VIP 窗口开始获取VIP任务--->
第 1 号 VIP 窗口开始为第1个号VIP客户服务~~~
3号【普通客户】等待服务^_^
2号【快速客户】等待服务^_^
第 1 号 快速 窗口完成为第1号快速客户服务,总共耗时1秒!
第 1 号 快速 窗口开始获取快速任务--->
第 1 号 快速 窗口开始为第2号快速客户服务~~~
第 2 号 普通 窗口开始获取 普通 任务-->
第 2 号 普通 窗口开始为第3号普通客户服务~~~
第 4 号 普通 窗口开始获取 普通 任务-->
第 4 号 普通 窗口没有取到普通任务,正在空闲一秒!
4号【普通客户】等待服务^_^
第 1 号 快速 窗口完成为第2号快速客户服务,总共耗时1秒!
第 1 号 快速 窗口开始获取快速任务--->
第 1 号 快速 窗口没有获取到 express 任务,获取 common 任务!
第 1 号 快速 窗口开始获取 普通 任务-->
第 1 号 快速 窗口开始为第4号普通客户服务~~~
第 4 号 普通 窗口开始获取 普通 任务-->
第 4 号 普通 窗口没有取到普通任务,正在空闲一秒!
第 1 号 VIP 窗口完成为第1号VIP客户服务,总共耗时2秒!
总结:
项目开发思路:由一个单例模式的号码管理机器管理着三个不同类型的客户号码管理器(普通,快速,vip),而每个类型的号码管理器可以添加该类型的客户号码与服务号码.服务窗口类(ServiceWindow)中,都会有自己的type类型和窗口编号,每个窗口在新线程中进行业务操作.MainClass测试类中,new出4个普通窗口,一个快速窗口和一个vip窗口,为每个窗口设置服务类型和编号,开启每个窗口的”叫号”动作,每个窗口就会从服务号码的集合中不挺的读取号码.最后测试类中为每个类型开始添加客户号码,根据比例不同,创建不同的定时器触发.这个项目比交通灯的项目稍微有点难度,还需要多多理解才是。
Java银行调度系统的更多相关文章
- Java——银行业务调度系统
需求: 模拟实现银行业务调度系统逻辑,具体需求如下: Ø 银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口. Ø 有三种对应类型的客户:VIP客户,普通 ...
- 黑马程序员:Java编程_7K面试题之银行业务调度系统
=========== ASP.Net+Android+IOS开发..Net培训.期待与您交流!=========== 模拟实现银行业务调度系统逻辑,具体需求如下: 银行内有6个业务窗口,1 - 4号 ...
- java基础---Java---面试题---银行业务调度系统(线程同步锁、枚举、线程池)
银行业务调度系统的项目需求: 模拟实现银行业务调度系统逻辑,具体需求如下: Ø 银行内有6个业务窗口,1- 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口. Ø 有三种对应类 ...
- 实验01——java模拟银行ATM系统
用java写的一个模拟银行系统,比较初级. ATM.java package cn.tedu.yinhang; import java.util.Scanner; /** * @author 赵瑞鑫 ...
- 黑马程序员_JAVA之银行业务调度系统
------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 1.模拟实现银行业务调度系统逻辑,具体需求如下: 银行内有6个业务窗口,1 - 4号窗口为普通窗 ...
- 又一道软通动力7K月薪面试题——银行业务调度系统
后期补充:网友对我诟病最多的就是我帮学生做面试题,说这是小偷和骗子行为,在此,我对自己给学员做面试题做出例如以下解释: (1)学员拿着面试题来找老师,学生也事先思考和尝试后实在没有办法,又求职心切才 ...
- java--银行业务调度系统
转载请申明出处:http://blog.csdn.net/xmxkf 1. 银行调度业务系统的题目来源与需求阐述 银行业务调度系统: 模拟实现银行业务调度系统逻辑,具体需求如下: 1.银行内有6个 ...
- Hulu大规模容器调度系统Capos
Hulu是美国领先的互联网专业视频服务平台,目前在美国拥有超过2000万付费用户.Hulu总部位于美国洛杉矶,北京办公室是仅次于总部的第二大研发中心,也是从Hulu成立伊始就具有重要战略地位的分支办公 ...
- 黑马程序员_java基础笔记(15)...银行业务调度系统_编码思路及代码
—————————— ASP.Net+Android+IOS开发..Net培训.期待与您交流!—————————— 1,面试题目:银行业务调度系统 模拟实现银行业务调度系统逻辑,具体需求如下: 银行内 ...
随机推荐
- [Python Cookbook] Pandas: 3 Ways to define a DataFrame
Using Series (Row-Wise) import pandas as pd purchase_1 = pd.Series({'Name': 'Chris', 'Item Purchased ...
- uva10857(状态压缩DP)
uva10857 题意 兔子希望在平面上 n 个点上放蛋,每个点最多放一个蛋,初始兔子在 (0, 0) 点,这里有无数个蛋,兔子可以回到这个点取蛋,兔子的速度为 \(v * 2^{-i}\)(i 为携 ...
- [xsy2579]counting
$\newcommand{\align}[1]{\begin{align*}#1\end{align*}}$题意:对于一个字符串$s$,定义$C(s)$为$s$中(出现次数最多的字母)出现的次数,问长 ...
- maven配置memcached.jar
由于目前java memcached client没有官方的maven repository可供使用,因此使用时需要手动将其安装到本地repository. java memcached client ...
- android RelativeLayout控件或view实现叠加效果
在开发android程序的时候,我们经常会遇到让控件或是view实现叠加的效果,一般这种情况,很多人会使用Framelayout来处理,可是有一个问题Framelayout布局在布局上会有很多限制,不 ...
- 【安居客】资深PHP软件开发工程师
工作职责: 1.网站项目的开发和维护: 2.负责技术部软件开发架构设计: 3.负责生产环境.测试环境和生产环境服务器运维和优化: 4.负责研究较前沿和复杂的技术运用: 岗位要求: 1.熟悉 PHP 程 ...
- SQL Server大量数据秒级插入/新增/删除
原文:SQL Server大量数据秒级插入/新增/删除 1.快速保存,该方法有四个参数,第一个参数为数据库连接,第二个参数为需要保存的DataTable,该参数的TableName属性需要设置为数据库 ...
- Java防止SQL注入的几个途径
java防SQL注入,最简单的办法是杜绝SQL拼接,SQL注入攻击能得逞是因为在原有SQL语句中加入了新的逻辑,如果使用 PreparedStatement来代替Statement来执行SQL语句,其 ...
- SuperMap iClient如何使用WMTS地图服务(转)
http://blog.sina.com.cn/s/blog_6259ebd50102v221.html 什么是WMTS服务 WMTS,切片地图Web服务(Web Map Tile Service)当 ...
- 2017年开发者生态报告:Python最多人想尝试的编程语言(转载)
在过去的十年里,Python 语言获得了最大的增长幅度,已经成为最受欢迎的程序设计语言之一.JetBrains 近日发布了 2017 开发者生态报告,该报告包含开发人员对 11 种编程语言以及数据库和 ...