----------------------ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
一、项目需求
- 共6个业务窗口,1-4是普通窗口,5是快速窗口,6是VIP窗口; 分别对应三种类型的客户: 普通客户, 快速客户, VIP客户
- 随机生成各种类型的客户, 生成各类型客户的概率比例为普通 : 快速 : VIP = 6 : 3 :1
- 客户办理业务时间有最大和最小值之分, VIP和普通客户所需服务时间在允许范围内随机设定, 快速客户为最小值
- 具体服务逻辑与现实生活相同, 如: 当VIP和快速窗口没有客户时, 可以为普通客户服务
- 面向对象的分析与设计
- 有三种对应类型的客户:VIP客户,普通客户,快速客户,异步随机生成各种类型的客户,各类型客户在其对应窗口按顺序依次办理业务。
每一个客户其实就是由银行的一个取号机器产生号码的方式来表示的。那么,我们需要有一个号码管理器对象,让这个对象不断地产生号码,就等于随机生成了客户。 - 由于有三类客户,并且每类客户的号码编排都是完全独立的,所以,这个系统一共要产生三个号码管理器对象,他们分别各自管理一类用户的排队号码。但是,银行的号码管理系统只能有一个,所以它需要设计成单例模式。
- 各种客户在各自窗口按顺序办理业务,转化为面向对象设计来说,我们可以认为是各个窗口在依次叫号。也就是每次都是通过号码管理器获取当前要被服务的号码。
二、具体实现
项目分析不再赘述。整个项目主体主要通过3个类实现。
紧记:谁拥有数据,谁就提供操作数据的方法。
- NumberMachine类 取号机器类,管理3个NumberManager
- NumberManager类 生成号码,同时给予号码
- ServiceWindow 类 为3类客户提供服务
下面是辅助类
- CustomerType类 枚举类 存储3类客户对象
- Constant类 常量类,存储客户的最大、最小、普通客户间隔时间
NumberManager类
package com.isoftstone.interview.bank;
import java.util.ArrayList;
import java.util.List;
/**声明一个号码管理类
* 定义一个用于存储上一个客户号码的成员变量和用于存储所有等待服务的客户号码的队列集合。
* 定义一个产生新号码的方法和获取马上要为之服务的号码的方法,这两个方法被不同的线程操作了相同的数据,所以,要进行同步。
* */
public class NumberManager
{
private int lastNumber=1;
private List<Integer> queueNumber= new ArrayList<Integer>();
public synchronized Integer generateNewNumber()
{
//把上一次个号码保存到队列中queueNumber.add(lastNumber);
return lastNumber++;
}
public synchronized Integer fetchServiceNumber()
{
Integer number=null;
if(queueNumber.size()>0)
//返回队列的首个号码
number=queueNumber.remove(0);
return number;
}
}
NumberMachine类
package com.isoftstone.interview.bank;
/** 声明一个取号机类*
* 通过号码管理器来生成三种类型的实例对象:普通客户管理器,快速客户管理器,VIP客户管理器
* * 定义三个方法来获得三种类型的客户对象* 把取号机类通过私有的构造方法形成単例类
* * 产生一个単例对象* 通过静态方法来获取単例的对象*/
publicclass NumberMachine
{
private NumberManager commonManager=new NumberManager();
private NumberManager expressManager=new NumberManager();
privateNumberManagervipManager=new NumberManager();
public NumberManager getCommonManager()
{
return commonManager;
}
public NumberManager getExpressManager()
{
return expressManager;
}
public NumberManager getVipManager()
{
return vipManager;
}
//设置成単例
private NumberMachine(){}
private static NumberMachine instance=new NumberMachine();
//访问単例的实例对象
public static NumberMachine getInstance()
{
return instance;
}
}
}
ServiceWindow 类
package com.isoftstone.interview.bank;
import java.util.Random;
import java.util.concurrent.Executors;
/** 定义一个服务窗口类*
* 定义一个叫号的方法,有服务窗口内部来完成的,不需要其他类来调用,所以由线程来完成叫号的功能。
* * 在线程内直接叫三种不同服务
* * 三种不同客户服务叫正在等待的号码,也就是获取一存储的号码
* * 根据最大值和最小值来得到随机获得服务时间
* * 最后得到的就是为这个客户所要花费的时间
* */
public class ServiceWindow
{
private CustomerType type=CustomerType.COMMON;
privateintwindowId=1;
public void setType(CustomerType type)
{
this.type = type;
}
public void setWindowId(int windowId)
{
this.windowId = windowId;
}
public void start()
{
//利用JAVA1.5的新特性吧任务交给线程池,线程池执行线程池中任意的任务。
Executors.newSingleThreadExecutor().execute(new Runnable()
{
publicvoid run()
{
while(true)
{
switch(type)
{
caseCOMMON:commonService();
break;
caseEXPRESS:expressService();
break;
caseVIP:vipService();
break;
}
}
}
});
}
private void commonService()
{
String windowName="第"+windowId+"号"+type+"窗口";
//得到正在等待的客户号码
Integer number=NumberMachine.getInstance().getCommonManager().fetchServiceNumber();
System.out.println(windowName+"正在获取任务");
if(number!=null)
{
System.out.println(windowName+"为第"+number+"个"+"普通"+"客户服务");
long beginTime=System.currentTimeMillis();
int maxRand=Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME;
//得到为客户所要用到的时间
long serveTime=new Random().nextInt(maxRand)+1+Constants.MIN_SERVICE_TIME;
try {
Thread.sleep(serveTime);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
long costTime=System.currentTimeMillis()-beginTime;
System.out.println(windowName+"为第"+number+"个"+"普通"+"客户完成服务,耗时"+costTime/1000+"秒");
}else
{
System.out.println(windowName+"没有取到服务任务,先休息1秒钟!");
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private void expressService()
{
String windowName="第"+windowId+"号"+type+"窗口";
Integer number=NumberMachine.getInstance().getExpressManager().fetchServiceNumber();
System.out.println(windowName+"正在获取任务");
if(number!=null)
{
System.out.println(windowName+"为第"+number+"个"+type+"客户服务");
long beginTime=System.currentTimeMillis();
//int maxServeTime=Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME;
// long serveTime=new Random().nextInt(+1+Constants.MIN_SERVICE_TIME);
try
{
Thread.sleep(Constants.MIN_SERVICE_TIME);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
long costTime=System.currentTimeMillis()-beginTime;
System.out.println(windowName+"为第"+number+"个"+type+"客户完成服务,耗时"+costTime/1000+"秒");
}else
{
System.out.println(windowName+"没有取到服务任务.");
commonService();
}
}
private void vipService()
{
String windowName="第"+windowId+"号"+type+"窗口";
Integer number=NumberMachine.getInstance().getCommonManager().fetchServiceNumber();
System.out.println(windowName+"正在获取任务");
if(number!=null)
{
System.out.println(windowName+"为第"+number+"个"+type+"客户服务");
long beginTime=System.currentTimeMillis();
int maxRand=Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME;
long serveTime=new Random().nextInt(maxRand)+1+Constants.MIN_SERVICE_TIME;
try {
Thread.sleep(serveTime);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
long costTime=System.currentTimeMillis()-beginTime;
System.out.println(windowName+"为第"+number+"个"+type+"客户完成服务,耗时"+costTime/1000+"秒");
}else
{
System.out.println(windowName+"没有取到服务任务!");
commonService();
}
}
}
}
}
}
}
CustomerType类
package com.isoftstone.interview.bank;
/** 声明一个客户类型的枚举类
* *
* 定义三种客户的类型
* *
* 覆盖父类的toString方法,三种客户类型以中文的形式出现
* */
publicenum CustomerType
{
COMMON,EXPRESS,VIP;
public String toString()
{
switch(this)
{
caseCOMMON:return"普通";
caseEXPRESS:return"快速";
caseVIP:return name();
}
returnnull;
}
}
Constant类
package com.isoftstone.interview.bank;
/**
* 定义三个静态常量* 分别表示最大服务时间,最小服务时间,普通客户间隔时间
* */
public class Constants
{
publicstaticintMAX_SERVICE_TIME=10000;
publicstaticintMIN_SERVICE_TIME=1000;
publicstaticintCOMMON_CUSTOMER_INTERVAL_TIME=1;
}
运行主体
package com.isfotstone.interview..bank;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/** 声明主类,并能独立运行* 创建三种类型的服务窗口对象
* * 利用线程池执行在一定的时间间隔内处理客户业务
* */
public class MainClass
{
/*@param args*/
public static void main(String[] args)
{
// TODO Auto-generated method stub
for(int i=1;i<5;i++)
{
ServiceWindow commonWindow=new ServiceWindow();
commonWindow.setWindowId(i);
commonWindow.start();
}
ServiceWindow expressWindow=new ServiceWindow ();
expressWindow.setType(CustomerType.EXPRESS);
expressWindow.start();
ServiceWindow wipWindow=new ServiceWindow ();
wipWindow.setType(CustomerType.VIP);
wipWindow.start();
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable()
{
publicvoid run()
{
Integer number=NumberMachine.getInstance().getCommonManager().generateNewNumber();
System.out.println(number+"号普通客户等待服务!");
}
},
0,
Constants.COMMON_CUSTOMER_INTERVAL_TIME,
TimeUnit.SECONDS);
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable()
{
publicvoid run()
{
Integer number=NumberMachine.getInstance().getExpressManager().generateNewNumber();
System.out.println(number+"号快速客户等待服务!");
}
},
0,
Constants.COMMON_CUSTOMER_INTERVAL_TIME * 2,TimeUnit.SECONDS);
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable()
{
publicvoid run()
{
Integer number=NumberMachine.getInstance().getVipManager().generateNewNumber();
System.out.println(number+"号VIP客户等待服务!");
}
},
0,
Constants.COMMON_CUSTOMER_INTERVAL_TIME * 6,TimeUnit.SECONDS);
}
}
}
}
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------