1. 银行业务系统的面向对象分析
1) 有三种对应类型的客户:VIP客户、普通用户、快速客户,异步随机产生各种客户(号码),各类型客户在窗口按顺序依次办理业务
2) 在每个窗口设置一个扫描器,对存储三种类型客户的数组进行扫描。如果存在相应客户,则取出客户,办理业务(该线程休眠)。如果VIP和快速窗口里没用客户,则去普通客户里去取。
3) 把三种用户类型定义为枚举,他们的字符串打印为中文格式。
4) 定义一个服务窗口(ServiceWindow),添加start方法,内部启动1个线程,根据服务窗口的类别(定义6个线程,4个普通窗口,1个vip窗口,一个快速窗口),分别循环调用三个不同的方法。
5) 打印出每个窗口在执行过程中的细节,以便于结果分析。
2. NumberManger类代码分析
1) 定义一个用于存储一个客户号码的 成员变量和用于存储等待服务的客户号码的队列集合。
2) 定义了一个产生新号码的方法和一个获取马上要为之服务的方法,这两个方法之间要进行线程同步。
源代码:
package cn.itcast.bankqueue;
import java.util.*;
public class NumberManager {
//最新的排队号
private int lastNumber=1;
//定义一个用来存储排队号的集合
private List<Integer> queueNumber=new ArrayList<Integer>();
//定义一个取号的方法
public synchronized Integer generateNewManager()
{
//把获得的最新号码存到集合中
queueNumber.add(lastNumber);
//返回添加的号码,并让新号码+1
return lastNumber++;
}
//获得集合中最靠前的号码
public synchronized Integer fetchServiceNumber()
{
//如果集合的长度不为0,移除输出的第一个元素并返回
if (queueNumber.size()!=0) {
return queueNumber.remove(0);
}
//如果集合长度为0,返回空
return null;
}
}
3. NumberMachine类
1) 定义三个成员变量分别指向三个NumberManager对象,分别表示普通、快速、VIP客户的号码管理器,定义三个方法来返回这三个NumberManger对象
2) 将NumberMachine设置成单例(只有一个取号器?)。
源代码分析:
package cn.itcast.bankqueue;
public class NumberMachine {
//设置一个普通客户管理器对象
private NumberManager commonManager=new NumberManager();
//设置一个快速客户管理器对象
private NumberManager expressManager=new NumberManager();
//设置一个vip客户管理器对象
private NumberManager vipManager=new NumberManager();
//用来分别返回这三个对象的方法
public NumberManager getCommonManager() {
return commonManager;
}
public NumberManager getExpressManager() {
return expressManager;
}
public NumberManager getVipManager() {
return vipManager;
}
//设计一个单例
private NumberMachine(){}
public static NumberMachine getInstance()
{
//NumberMachine instance=new NumberMachine();
return instance;
}
private static NumberMachine instance=new NumberMachine();
}
思考:单例的方法和成员都是静态的。是否可以在方法内定义对象。
4. CustomerType枚举类和Constant类
1) 系统中有三种类型的客户,所以定义一个枚举类,其中三个成员分别表示三种类型的客户。
2) 重写toString方法,返回类型的中文名称。
源代码分析:
package cn.itcast.bankqueue;
public enum CustomerType {
//定义三种类型的客户
COMMON,EXPRESS,VIP;
//重写toString方法
public String toString()
{
switch (this) {
case COMMON:
return "普通";
case EXPRESS:
return "快速";
case VIP:
return name();
}
return null;
}
}
1) Contants类定义三个常量:MAX_SERVICE_TIME(窗口最大服务时间)、MIN_SERVICE_TIME(窗口最大服务时间)、COMMON_CUSTOMER_INTERVAL_TIME(普通用户产生的时间间隔)
package cn.itcast.bankqueue;
public class Constants {
//服务最大时间
public static int MAX_SERVICE_TIME=10000;
//服务最小时间
public static int MIN_SERVICE_TIME=1000;
//普通用户到来的时间间隔
public static int COMMON_CUSTOMER_INTERVAL_TIME=1;
}
5. ServiceWindow类
1) 定义一个start方法,内部启动一个线程,根据服务窗口的类别分别循环调用三个不同德方法。
2) 定义三个方法分别对三类客户进行服务,为了观察运行效果打印出详细信息。
源代码分析:
package cn.itcast.bankqueue;
import java.util.Random;
import java.util.concurrent.Executors;
public class ServiceWindow {
//设置用户类型的属性
private CustomerType type=CustomerType.COMMON;
//设置装口编码的属性
private int windowId=1;
public void setType(CustomerType type) {
this.type = type;
}
public void setWindowId(int windowId) {
this.windowId = windowId;
}
//编写start方法
public void start()
{
//开启一个新的线程
Executors.newSingleThreadExecutor().execute(new Runnable(){
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+"窗口";
//去普通用户的队列里查找最靠前的用户并返回用户号码。
Integer number= NumberMachine.getInstance().getCommonManager().fetchServiceNumber();
//提示xx窗口开始获取服务
System.out.println(windowName+"正在获取任务...");
//如果普通用户队列里取出了用户,则进入if语句
if (number!=null) {
//提示xx窗口为xx客户服务
System.out.println(windowName+"正在为"+number+"号"+"普通"+"客户服务!");
//服务开始时间
long beginTime=System.currentTimeMillis();
//产生随机数范围(9000)
int maxRand=Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME;
//产生随机服务时间(1-10s)
long serveTime=new Random().nextInt(maxRand)+1+Constants.MIN_SERVICE_TIME;
try {
//开始为用户服务(该线程开始休眠)
Thread.sleep(serveTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
//获得该次服务耗费的时间
long costTime=System.currentTimeMillis()-beginTime;
//打印服务信息
System.out.println(windowName+"为第"+number+"个"+"普通"+"客户完成服务!:耗时"+costTime/1000+"秒");
} else {
//如果队列中没有客户则该银行职员休息1秒
System.out.println(windowName+"没有取到任务,先休息1秒钟");
try {
//银行职员开始休息
Thread.sleep(1000);
} catch (InterruptedException e) {
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();
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("第"+windowId+"号"+type+"窗口没有取到任务");
//如果快速窗口没有取到快速客户,则去普通客户窗口去取
commonService();
}
}
//VIP用户
private void VIPService() {
String windowName="第"+windowId+"号"+type+"窗口";
Integer number= NumberMachine.getInstance().getVipManager().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("第"+windowId+"号"+type+"窗口没有取到任务");
//如果vip窗口没有取到vip客户,则去普通客户窗口去取
commonService();
}
}
}
6. MainClass类
1) 用for循环创建出4个普通窗口,再创建一个VIP窗口,一个快速窗口。
2) 创建三个定时器,分别定时去创建普通用户、快速客户和vip客户。
package cn.itcast.bankqueue;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class MainClass {
public static void main(String[] args) {
//定义4个普通窗口
for (int i = 1; i < 5; i++) {
ServiceWindow commonwindow=new ServiceWindow();
//设置普通窗口ID
commonwindow.setWindowId(i);
//开启普通窗口的服务
commonwindow.start();
}
//定义一个VIP窗口
ServiceWindow vipwindow=new ServiceWindow();
//设置窗口的类型
vipwindow.setType(CustomerType.VIP);
vipwindow.start();
//定义一个快速窗口
ServiceWindow expresswindow=new ServiceWindow();
//设置窗口的类型为快速窗口
expresswindow.setType(CustomerType.EXPRESS);
expresswindow.start();
//定时产生一个普通客户
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable()
{
public void run() {
//产生一个客户,并返回该客户的编号
Integer number= NumberMachine.getInstance().getCommonManager().generateNewManager();
//显示xx号客户开始等待服务
System.out.println(number+"号普通客户等待服务!");
}
},
0,
Constants.COMMON_CUSTOMER_INTERVAL_TIME,
TimeUnit.SECONDS
);
//vip客户
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable()
{
public void run() {
Integer number= NumberMachine.getInstance().getVipManager().generateNewManager();
System.out.println(number+"号VIP客户等待服务!");
}
},
0,
6*Constants.COMMON_CUSTOMER_INTERVAL_TIME,
TimeUnit.SECONDS
);
//快速客户
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable()
{
public void run() {
Integer number= NumberMachine.getInstance().getExpressManager().generateNewManager();
System.out.println(number+"号快速客户等待服务!");
}
},
0,
2*Constants.COMMON_CUSTOMER_INTERVAL_TIME,
TimeUnit.SECONDS
);
}
}
总结;勤学多练,希望有一天我也能写出这样优秀的代码。