银行业务调度系统
1,明确需求。我要做什么?
2,分析思路。我要怎么做?1,2,3。
3,确定步骤。每一个思路部分用到哪些语句,方法,和对象。
4,代码实现。用具体的java语言代码把思路体现出来。
1.银行业务调度系统,三种类型的客户或者说是服务(common,express,vip),客户的比例是6 3 1,每个客户的服务时间在最大值10和最小值1之间,express客户的时间总是最小值1,1-4窗口为common服务,5号和6号分别为express和vip窗口,当vip窗口和express窗口没有客户等待服务的时候可以处理common服务,而一旦有对应的客户等待服务,则需要优先处理。
2 1.定义NumberManager类 2.定义NumberMachine类 3.定义CustomerType类 4.定义ServiceWindow类 5.定义Constants类6.定义主函数类
3.1.成员变量lastNumber,queueNumber的ArrayList集合,generateNewNumber方法添加lastNumber并返回lastNumber,fetchNumber方法,当集合大于0时,删除0角标元素,返回remove方法的返回值,否则返回null
3.2单例设计创建对象NumberMachine instance,创建三个类型的Manager对象,相应的方法为getCommonManager,并返回需要的commonManager
3.3三种类型的客户用枚举产生,COMMON,EXPRESS,VIP,复写toString方法,定义局部变量name,使用switch函数匹配各个类型将name赋值为对应的“普通”,“快速”,“VIP”
3.4私有type并赋值CustomerType.COMMON,私有成员变量number并赋值1,对type构建set和get方法,并对number构建set方法,start方法,创建匿名线程池,在参数位上传递匿名Runnable接口的匿名内部类并复写run方法,使用switch循环匹配类型,并调用对应类型的方法, commonService方法,定义窗口名字windowName,某窗口开始获取普通任务,定义serviceNumber并被commonManager的方法fetchNumber得到的号码赋值,判断如果serviceNumber非空,打印某窗口为此号码服务,定义maxRandom表示最大的服务时间并被最大值和最小值的差赋值,定义serviceTime并被maxRandom产生的随机数赋值,线程sleep serviceTime时间,之后打印某窗口完成第几号普通服务,如果serviceNumber为空,则打印没有获取普通任务,照此接着定义其他两类服务的方法
3.5 定义三个静态int类型的常量MAX_SERVICE_TIME=10000,MIN_SERVICE_TIME=1000,COMMON_CUSTOMER_INTERVAL_TIME=1
3.6私有并静态成员变量logger,初始化关联“cn.itcast.bankqueue”for循环创建普通窗口,并赋值1,2,3,4,后开启窗口,创建其他两个窗口并分别设置type为EXPRESS和VIP并开启窗口,产生定时器参数传递一个匿名Runnable接口子类,并复写run方法,定义serviceNumber并被CommonManager的方法generateNewNumber的返回值赋值,打印第几号普通客户正在等待服务,接着相应地定义快速客户和vip客户拿号
问题:为什么ServiceNumber中的方法要私有??
类中的成员或者方法一般都会定义为私有,只在本类中有效,不需要对外提供
整个银行业务调度系统的程序耗了太长的时间了,倒不如多花点时间在基础的知识上,基础不牢,单靠这样高强度的练习是过于仓促的,就好比还没有学会走就想跑了,所以还是多抓 一些基础的东西才行
改进思路:
一、系统的取号机只有三种方式的取号(普通客户,快速客户,vip客户),所以采用枚举的方式是比较合适的,因为枚举能产生固定个数的对象,用起来也比较方便。
二、创建普通服务窗口类,下面有两个子类(快速服务窗口和vip服务窗口)。这一点张老师在视频中也讲了,不过没有在课堂上实现,我把它实现了,这样就提高了代码的复用性。
三、根据系统需求的描述,是6个窗口按次序排列,1 -4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。而不是1号快速窗口和1号VIP窗口,这一点我也做了改进,更符合项目要求。
四、服务窗口不用每隔1秒检查,服务完后就检查是否有客户等待服务,而且最好不打印“没取得任务,空闲一秒”,因为作为模拟场景的输出,这样的阅读性不是很好。
五、客户取得号码的时候显示前面有几人在排队字样,如“9号VIP客户,欢迎光临,您前面有1位客户”,这样更符合真实场景。
六、按照项目需求的要求,异步随机生成各种类型的客户,生成各类型用户的概率比例为: VIP客户 :普通客户 :快速客户 = 1 :6 :3,所以满足比例的同时,具体时间也应该是随机的,而不是固定的。
package com.itheima.bank;
public class MainClass {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
for(int i=1;i<5;i++){
ServiceWindow sw=null;
sw=new ServiceWindow(i,QueueMachine.COMMON);
sw.start();
}
new ExpressServiceWindow(5,QueueMachine.EXPRESS).start();
new VipServiceWindow(6,QueueMachine.VIP).start();
QueueMachine.COMMON.start();
QueueMachine.EXPRESS.start();
QueueMachine.VIP.start();
}
}
package com.itheima.bank;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public enum QueueMachine {
COMMON, EXPRESS, VIP;
private List<Integer> commonList = new ArrayList<Integer>();
private List<Integer> expressList = new ArrayList<Integer>();
private List<Integer> vipList = new ArrayList<Integer>();
private static Integer customerNum = 1;// commonNum=1,expressNum=1,vipNum=1;
public String toString() {
String type = null;
if (this == COMMON)
type = "普通客户";
if (this == EXPRESS)
type = "快速客户";
if (this == VIP)
type = "VIP客户";
return type;
}
public synchronized void start() {
long period = 0;
switch (this) {
case COMMON:
period = new Random().nextInt(3) + 1;
break;
case EXPRESS:
period = new Random().nextInt(6) + 1;
break;
case VIP:
period = new Random().nextInt(18) + 1;
break;
}
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
public void run() {
switch (QueueMachine.this) {// 重点
case COMMON:
System.out.println(customerNum + "号普通业务客户,欢迎光临,您前面有"
+ commonList.size() + "位客户");
commonList.add(customerNum++);
break;
case EXPRESS:
System.out.println(customerNum + "号快速业务客户,欢迎光临,您前面有"
+ expressList.size() + "位客户");
expressList.add(customerNum++);
break;
case VIP:
System.out.println(customerNum + "号VIP客户,欢迎光临,您前面有"
+ vipList.size() + "位客户");
vipList.add(customerNum++);
break;
}
}
}, 0, period, TimeUnit.SECONDS);
}
public synchronized Integer fetchNum() {
Integer fn = null;
switch (this) {
case COMMON:
if (commonList.size() > 0)
fn = commonList.remove(0);
break;
case EXPRESS:
if (expressList.size() > 0)
fn = expressList.remove(0);
break;
case VIP:
if (vipList.size() > 0)
fn = vipList.remove(0);
break;
}
return fn;
}
}
package com.itheima.bank;
import java.util.Random;
import java.util.concurrent.Executors;
public class ServiceWindow {
public int windowNum=1;
public QueueMachine type=QueueMachine.COMMON;
public static final int MIN_TIME=1000,MAX_TIME=3000;
public ServiceWindow(int windowNum,QueueMachine type){
this.type=type;
this.windowNum=windowNum;
}
public void start(){
Executors.newSingleThreadExecutor().execute(new Runnable(){
public void run(){
System.out.println("服务窗口"+windowNum+"("+type.toString()+")开启!");
while(true){
Integer customerNum = fetchNum();
if (customerNum!=null){
System.out.println("窗口"+windowNum+"为"+type.toString()+customerNum+"服务!");
long startTime=System.currentTimeMillis();
int serviceTime=MIN_TIME+(new Random().nextInt(MAX_TIME-MIN_TIME)+1);
try {
sleepTime(serviceTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long endTime=System.currentTimeMillis();
System.out.println("窗口"+windowNum+"为"+type.toString()+
customerNum+"服务完毕!耗时"+(endTime-startTime)/1000+"秒");
}
else{
extend();
}
}
}
});
}
protected Integer fetchNum() {
Integer customerNum=QueueMachine.COMMON.fetchNum();
return customerNum;
}
protected void sleepTime(int serviceTime)
throws InterruptedException {
Thread.sleep(serviceTime);
}
protected void extend(){
}
}
class ExpressServiceWindow extends ServiceWindow{
public int windowNum=5;
public QueueMachine type=QueueMachine.EXPRESS;
public ExpressServiceWindow(int windowNum,QueueMachine type){
super(windowNum, type);
this.type=type;
this.windowNum=windowNum;
}
protected Integer fetchNum() {
Integer customerNum=QueueMachine.EXPRESS.fetchNum();
return customerNum;
}
protected void sleepTime(int serviceTime)
throws InterruptedException {
Thread.sleep(MIN_TIME);
}
protected void extend(){
Integer commonCustomerNum =QueueMachine.COMMON.fetchNum();
if (commonCustomerNum!=null){
System.out.println("窗口"+windowNum+"为"+"普通客户"+commonCustomerNum+"服务!");
long startTime=System.currentTimeMillis();
int serviceTime=MIN_TIME+(new Random().nextInt(MAX_TIME-MIN_TIME)+1);
try {
Thread.sleep(serviceTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long endTime=System.currentTimeMillis();
System.out.println("窗口"+windowNum+"为"+"普通客户"+
commonCustomerNum+"服务完毕!耗时"+(endTime-startTime)/1000+"秒");
}
}
}
class VipServiceWindow extends ServiceWindow{
public int windowNum=6;
public QueueMachine type=QueueMachine.VIP;
public VipServiceWindow(int windowNum,QueueMachine type){
super(windowNum, type);
this.type=type;
this.windowNum=windowNum;
}
protected Integer fetchNum() {
Integer customerNum=QueueMachine.EXPRESS.fetchNum();
return customerNum;
}
protected void sleepTime(int serviceTime)
throws InterruptedException {
Thread.sleep(serviceTime);
}
protected void extend(){
Integer commonCustomerNum =QueueMachine.COMMON.fetchNum();
if (commonCustomerNum!=null){
System.out.println("窗口"+windowNum+"为"+"普通客户"+commonCustomerNum+"服务!");
long startTime=System.currentTimeMillis();
int serviceTime=MIN_TIME+(new Random().nextInt(MAX_TIME-MIN_TIME)+1);
try {
sleepTime(serviceTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long endTime=System.currentTimeMillis();
System.out.println("窗口"+windowNum+"为"+"普通客户"+
commonCustomerNum+"服务完毕!耗时"+(endTime-startTime)/1000+"秒");
}
}
}