---------- android培训 java培训 期待与您交流!------------
先上需求:
银行业务调度系统
模拟实现银行业务调度系统逻辑,具体需求如下:
银行内有6个业务窗口,1- 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。
有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。
异步随机生成各种类型的客户,生成各类型用户的概率比例为:
VIP客户 :普通客户 :快速客户 = 1 :6 :3。
客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需的时间,快速客户办理业务所需时间为最小值(提示:办理业务的过程可通过线程Sleep的方式模拟)。
各类型客户在其对应窗口按顺序依次办理业务。
当VIP(6号)窗口和快速业务(5号)窗口没有客户等待办理业务的时候,这两个窗口可以处理普通客户的业务,而一旦有对应的客户等待办理业务的时候,则优先处理对应客户的业务。
随机生成客户时间间隔以及业务办理时间最大值和最小值自定,可以设置。
不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。
--------------------------------------------------------------------------------------------------------------
分析:
客户进入银行先分类型取票排队,然后等待服务窗口叫号。所以我觉得计数器应该拥有客户排队的数据,那么编号就当作是一个个客户,计数器就拥有对外访问客户的方法,而窗口就向计数器询问有没有下一个客户,如果没有就换普通类型再询问有没有,如果始终没有下一个客户,那么就休息一下再继续
快速窗口和vip窗口在没有对应客户的情况下还要为普通客户服务。所以窗口类中应该有判断类型的方法
由于服务的时间有最大值和最小值,为了体现面向对象的思想,就将时间封装成一个类。
下面就进行代码的分析,自己没有照着老师教的抄,而是以自己的思想做一遍,体会其中的差距,理解老师每一步为什么要那么做。
最后总结分析出自己虽然也能将代码做出来,但没有将任何事物看作对象来对待,面向对象的体会也许就只能在实际的项目经验中去积累。
窗口类型:
/**
* 由于窗口类型是不变的,分别对应 普通 快速 VIP
* @author 不信
*
*/
public enum windowType {
COMMON,FAST,VIP;
//覆盖父类的toString()
public String toString()
{
switch (this) {
case COMMON:
return "普通";
case FAST:
return "快速";
default:
return name();
}
}
//用户类型对应服务时间,其中快速客户为最小值也就是1秒
public int useTime()
{
if(this != FAST)
return Constants.MAX_SERVICE_TIME;
else {
return Constants.MIN_SERVICE_TIME;
}
}
}
服务时间的最大值和最小值:
/**
* 服务时间的最小值与最大值
* @author 不信
*
*/
public class Constants {
public static int MAX_SERVICE_TIME = 10; //10秒!
public static int MIN_SERVICE_TIME = 1; //1秒!
}
计数器,里面包含了客户的排队顺序
import java.util.LinkedList;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* 这是一个计数器类,由于顾客领了票就说明排了队,所以计数器拥有顾客
* 服务窗口可以问计数器有没有顾客
*
* */
public class counter {
//顾客排队的号
private int num = 1;
//顾客类型不一样,办理业务所用的时间也就不一样
private int time;
//顾客类型
private windowType type;
//存储顾客排队的号
private LinkedList<Integer> list = new LinkedList<Integer>();
//计数器类是一开始就有类型与办理业务所需的最大时间
public counter(int time,windowType type)
{
this.time = time;
this.type = type;
addList();
}
//定时进入一位顾客,由于顾客类型的不一样,光临的时间也不一样
public synchronized void addList()
{
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable() {
@Override
public void run() {
list.addLast(num++);
}
},
0,
time,
TimeUnit.SECONDS
);
System.out.println("第"+num+"位"+type.toString()+"客户等待服务");
}
//服务窗口调用这个方法来获取正在排队的客户,如果没有返回null
public synchronized Integer take()
{
if(!list.isEmpty())
return list.removeFirst();
else {
return null;
}
}
}
三种窗口类型对应了三种客户类型
/**
* 三种客户类型的对象,提供对外访问的静态方法,服务窗口其实就是根据类型来访问的
* @author 不信
*
*/
public class client {
private static counter COMMONCLIENT = new counter(1, windowType.COMMON);
private static counter FASTCLIENT = new counter(3,windowType.FAST);
private static counter VIPCLIENT = new counter(6, windowType.VIP);
private client(){}
public static counter getClient(windowType type)
{
switch (type) {
case COMMON:
return COMMONCLIENT;
case FAST:
return FASTCLIENT;
default:
return VIPCLIENT;
}
}
服务窗口
import java.util.Random;
import java.util.concurrent.Executors;
/**
* 服务窗口类
* @author 不信
*
*/
public class window {
//每个窗口都有自己对应的类型
private windowType type;
//每个窗口都有自己的编号
private int num;
//在初始化时,就有了类型和编号
public window(windowType type, int num)
{
this.type = type;
this.num = num;
}
//窗口开始工作
public void windower()
{
System.out.println("第"+num+"号"+this.type+"窗口开始服务");
//创建一个线程池,其中只有一个线程
Executors.newSingleThreadExecutor().execute(new Runnable() {
@Override
public void run() {
while(true)
{
System.out.println("第"+num+"号"+window.this.type+"窗口正在等待客户");
//调用窗口的工作内容
work(type);
}
}
});
}
//窗口工作的内容
public void work(windowType type)
{
//窗口寻找对应类型的客户是否存在,如果存在就给予服务,如果不存在就执行 else if()
Integer i = client.getClient(type).take();
if(i!=null){
System.out.println("第"+num+"号"+this.type+"窗口正在为第"+i+"位"
+type+"客户服务");
//以客户的类型计算出要给服务的时间
int randomTime = new Random().nextInt(type.useTime())+1;
try {
//这里以线程 sleep()的形式模仿
Thread.sleep(randomTime*1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//当线程“醒”来时,就给对应得客户服务完毕
System.out.println("第"+num+"号"+this.type+"窗口为第"+i+"位"
+type+"客户服务耗时"+randomTime+"秒");
}
//由于vip窗口和快速窗口在没有对应客户存在的情况下,还要给普通客户服务所以这里使用了递归
else if(type != windowType.COMMON)
{
work(windowType.COMMON);
}
else{
//如果始终没有需要服务的客户,就sleep()休息一秒,醒来继续查找
System.out.println("第"+num+"号"+this.type+"窗口没有取到任务,正在休息一秒");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
最后主函数调用:
public class MainClass {
public static void main(String[] args)
{
//四个普通窗口
for(int i = 1;i < 5;i++)
{
new window(windowType.COMMON, i).windower();
}
//一个快速窗口 和一个VIP窗口
new window(windowType.FAST, 5).windower();
new window(windowType.VIP, 6).windower();
}
}
运行结果如图
---------- android培训 java培训 期待与您交流!------------
详情请点击:http://edu.csdn.net/