----------android培训、java培训、期待与您交流!----------
1.项目需求:
模拟实现银行业务调度系统逻辑,具体需求如下:
银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。
有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。
异步随机生成各种类型的客户,生成各类型用户的概率比例为:
VIP客户:普通客户:快速客户 = 1:6:3。
各类型客户在其对应窗口按顺序依次办理业务。
当 VIP ( 6 号)窗口和快速业务( 5 号)窗口没有客户等待办理业务的时候,这两个窗口可以处理普通客户的业务,而一旦有对应的客户等待办理业务的时候,则优先处理对应客户的业务。
随机生成客户时间间隔以及业务办理时间最大值和最小值自定,可以设置。
不要求实现 GUI ,只考虑系统逻辑实现,可通过 Log 方式展现程序运行结果。
2.面向对象的分析与设计
根据需求需定义的类及其需要实现的功能为:
2.1取号机器:
营业厅内的取号机器,1台取号机器上能取3种不同类型的号,3种不同类型的号应该是分开独立排序的(这个可以用集合来存储)。
取号机器应该对提供客户不同类型的取号功能,根据客户需要服务自行取对应服务类型的号。
取号机器应该对各个窗口提供不同类型的叫号功能,当有客户排队等待服务时,服务窗口叫号,取号机器将相应客户从排队人员中去除。
2.2营业厅
营业厅应该知道何时各种类型客户来到营业厅在排队等待服务,即:何时营业厅内等待服务的客户数增加及其数量。而且每种客户数量的增加都是独立的,相互不影响,应该对应的线程。
2.3服务窗口
服务窗口,应该知道自己的窗口编号和自己的类型及能提供的对应服务。
当VIP窗口和快速业务窗口没有客户等待办理业务的时候,这两个窗口可以处理普通客户的业务,而一旦有对应的客户等待办理业务的时候,则优先处理对应客户的业务。
6个窗口是分开独立运行互不干扰的,应用多线程。
2.4主类
提供代码执行的入口
2.5常量类
存储所需的一些常量
3.代码编写
3.1取号机器
import java.util.*;
public enum NumerMachine{
//定义3种号码的取号系统
COMMON_NUMBERMANAGER,VIP_NUMBERMANAGER,QUICK_NUMBER;
private List<Integer> queueNumbers = new ArrayList<Integer>();//定义集合存储对应类型客户排队数量
private int lastnumber=0;
public synchronized void generateNewNumber(){//定义排号方式。营业厅每种对应客户来1个,对应类型排号就自增1次
queueNumbers.add(++lastnumber);
}
public synchronized Integer fetchNumber(){//定义消号方式。 当有客户排队时,窗口就叫1次号。服务完该客户,对应类型号码就从排队集合中去除。
if(queueNumbers.size()>0){
return queueNumbers.remove(0);
}
else
return null;
}
3.2营业厅
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Hall {
public Hall(){
ScheduledExecutorService commoner= Executors.newScheduledThreadPool(1);//每1秒产生1个普通客户来取号
commoner.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
NumerMachine.COMMON_NUMBERMANAGER.generateNewNumber();
}
},
Constants.COMMON_CUSTOMER_INTERVAL_TIME,
Constants.COMMON_CUSTOMER_INTERVAL_TIME,
TimeUnit.SECONDS);
ScheduledExecutorService VIPer= Executors.newScheduledThreadPool(1);//每6秒产生1个VIP客户来取号
VIPer.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
NumerMachine.VIP_NUMBERMANAGER.generateNewNumber();
}
},
Constants.COMMON_CUSTOMER_INTERVAL_TIME*6,
Constants.COMMON_CUSTOMER_INTERVAL_TIME*6,
TimeUnit.SECONDS);
ScheduledExecutorService Quicker= Executors.newScheduledThreadPool(1);//每2秒产生1个快速客户来取号
Quicker.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
NumerMachine.QUICK_NUMBER.generateNewNumber();
}
},
Constants.COMMON_CUSTOMER_INTERVAL_TIME*2,
Constants.COMMON_CUSTOMER_INTERVAL_TIME*2,
TimeUnit.SECONDS);
}
}
3.3服务窗口
import java.util.Random;
public class Window implements Runnable{
private String type;//设定窗口类型
private int windownumber;//设定窗口编号
public Window(int windownumber,String type){//定义构造函数
this.type=type;
this.windownumber=windownumber;
System.out.println(this+"窗口开始工作了");
}
@Override
public String toString(){//覆盖toString方法
return type+Integer.toString(windownumber);
}
@Override
public void run(){
while(true){
switch(type){//根据窗口类型,执行对应能提供的服务
case"普通":CommonSerice();
break;
case"VIP":VIPSerice();
break;
case"快速":quickSerice();
}
}
}
private void CommonSerice() {//设定普通窗口所能提供的服务
Integer commonnumber=null;
if((commonnumber=NumerMachine.COMMON_NUMBERMANAGER.fetchNumber())!=null){
System.out.println(windownumber+"号"+type+"窗口在为第"+commonnumber+"号普通客户服务");
int maxRandom=Constants.MAXTIME-Constants.MINTIME;
int serviceTime=new Random().nextInt(maxRandom)+1+Constants.MINTIME;
try {
Thread.sleep(serviceTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(windownumber+"号"+type+"窗口为第"+commonnumber+"号普通客户服务完毕耗时"+serviceTime/1000 + "秒");
}
else
System.out.println(windownumber+"号"+type+"窗口没有取到号,休息1秒");
try {
Thread.sleep(1000);
} catch (InterruptedException e){
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void VIPSerice(){//设定VIP窗口所能提供的服务
Integer VIPnumber=null;
if((VIPnumber=NumerMachine.VIP_NUMBERMANAGER.fetchNumber())!=null){
System.out.println(windownumber+"号"+type+"窗口在为第"+VIPnumber+"号VIP客户服务");
int maxRandom=Constants.MAXTIME-Constants.MINTIME;
int serviceTime=new Random().nextInt(maxRandom)+1+Constants.MINTIME;
try {
Thread.sleep(serviceTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(windownumber+"号"+type+"窗口为第"+VIPnumber+"号VIP客户服务完毕耗时"+serviceTime/1000 + "秒");
}
else
CommonSerice();//没有VIP客户排队时,即看是否有普通客户排队等待服务
}
private void quickSerice(){//设定快速窗口所能提供的服务
Integer Quicknumber=null;
if((Quicknumber=NumerMachine.QUICK_NUMBER.fetchNumber())!=null){
System.out.println(windownumber+"号"+type+"窗口在为第"+Quicknumber+"号快速客户服务");
int serviceTime=Constants.MINTIME;
try {
Thread.sleep(serviceTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(windownumber+"号"+type+"窗口为第"+Quicknumber+"号快速客户服务完毕耗时"+serviceTime/1000 + "秒");
}
else
CommonSerice();//没有快速客户排队时,即看是否有普通客户排队等待服务
}
}
3.4主类:
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args){
String[] names={"","普通","普通","普通","普通","快速","VIP"};
Hall hall=new Hall();//创建营业厅
for(int x=1;x<7;x++){//创建4个普通窗口和1个快速窗口和1个VIP窗口
Window window=new Window(x, names[x]);
Executors.newSingleThreadExecutor().execute(window);
}
}
}
3.5常量类
public class Constants {
final static int MINTIME=1000;//设定最小办理业务所需时间
final static int MAXTIME=10000;//设定最大办理业务所需时间
/*每个普通窗口服务一个客户的平均时间为5秒,一共有4个这样的窗口,也就是说银行的所有普通窗口合起来
* 平均1.25秒内可以服务完一个普通客户,再加上快速窗口和VIP窗口也可以服务普通客户,所以,
* 1秒钟产生一个普通客户比较合理,*/
final static int COMMON_CUSTOMER_INTERVAL_TIME = 1; //设定产生普通客户时间
}