首先定义
号码管理类
要有取号的方法,将号码加入到集合中去
要有得到号码的方法。(每次取出集合中的第一个)
都是多线程操作,所以要synchronized
public class NumberManager {
private int lastNumber = 0;
private List
public synchronized int generateNewManager() {
lastNumber = lastNumber + 1;
queueNumber.add(lastNumber);
return lastNumber;
}
public synchronized Integer fetchServiceNumber()// 这里用int的话,如果集合为空的时候remove(0)就会返回一个空,就会出现空指针异常
{
Integer number = null;
if (queueNumber.size() > 0) {
number = queueNumber.remove(0);// 从集合中取出第一个数字,也就是排队的第一个
}
return number;
}
}
第二,要有一个号码机器类
产生3种号码管理。new出三个号码管理,并且可以得到这三个对象
只有一个号码机器提供号码,所以要是单例模式
public class NumberMachine {
private NumberMachine() {}// 单例模式
private NumberManager commonManager = new NumberManager();
private NumberManager expressManager = new NumberManager();
private NumberManager vipManager = new NumberManager();
public NumberManager getCommonManager() {
return commonManager;
}
public NumberManager getExpressManager() {
return expressManager;
}
public NumberManager getVipManager() {
return vipManager;
}
private static NumberMachine instance = new NumberMachine();
public static NumberMachine getInstance() {
return instance;
}
}
第三写一个服务窗口类
要有一个窗口类型的属性,有赋给的方法
要有一个开始(start)方法:有一个线程池
判断是哪种类型的客户给出不同的服务
普通服务的方法:从号码机器得到普通的号码管理,取得普通号码
得到 ?开始服务,到结束服务,在执行start方法
没得到?休息一秒,在次执行start方法
快速服务的方法:
VIP服务的方法;
从号码机器得到相应的号码管理,取得相应号码
得到 ?开始服务,到结束服务,在执行start方法
没得到?直接执行普通服务方法
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;
}
public void start() {
// 线程池
Executors.newSingleThreadExecutor().execute(new Runnable() {
public void run() {// switch效率要比if else高
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();
System.out.println(windowName + " 开始获取 普通 任务");
if (number != null) {
System.out.println(windowName + " 为第 " + number + " 号 普通 客户服务");
long beginTime = System.currentTimeMillis();
long serverTime = Constants.MIN_SERVICE_TIME
+ ((int) (Math.random()
* (Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME) + 1));
try {
Thread.sleep(serverTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println(windowName + " 为第 " + number + " 号客户服务,耗时 "
+ (endTime - beginTime) / 1000 + " 秒");
start();
} else {
System.out.println(windowName + " 没有取到 普通 任务,空闲一秒");
try {
Thread.sleep(1000);
start();// 这里可以在start方法中写一个循环,就不用加了
} 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 + " 号 快速 客户服务");
long beginTime = System.currentTimeMillis();
long serverTime = Constants.MIN_SERVICE_TIME;
try {
Thread.sleep(serverTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println(windowName + " 为第 " + number + " 号客户服务,耗时 "
+ (endTime - beginTime) / 1000 + " 秒");
start();
} else {
System.out.println(windowName + " 没有取到取 快速 任务,获取 普通 任务");
commonService();
}
}
private void vipService() {
String windowName = "第 " + windowId + " 号 " + type + " 窗口";
Integer number = NumberMachine.getInstance().getVipManager()
.fetchServiceNumber();
System.out.println(windowName + " 开始获取 vip 任务");
if (number != null) {
System.out.println(windowName + " 为第 " + number + " 号 vip 客户服务");
long beginTime = System.currentTimeMillis();
long serverTime = Constants.MIN_SERVICE_TIME
+ ((int) (Math.random()
* (Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME) + 1));
try {
Thread.sleep(serverTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println(windowName + " 为第 " + number + " 号客户服务,耗时 "
+ (endTime - beginTime) / 1000 + " 秒");
start();
} else {
System.out.println(windowName + " 没有取到 vip 任务,获取 普通 任务");
commonService();
}
}
}
第四写一个主类
创建4个普通窗口,开始工作,start();
创建1个快速窗口,开始工作,start();
创建1个VIP窗口,开始工作,start();
开启三个定时器,分别以不同的速度来不同的客户
public class MainClass {
public static void main(String[] args){
for(int i=1;i<=4;i++)
{
ServiceWindow commonWindow=new ServiceWindow();
commonWindow.setWindowId(i);
commonWindow.setType(CustomerType.COMMON);
commonWindow.start();
}
ServiceWindow expressWindow=new ServiceWindow();
expressWindow.setWindowId(5);
expressWindow.setType(CustomerType.EXPRESS);
expressWindow.start();
ServiceWindow vipWindow=new ServiceWindow();
vipWindow.setWindowId(6);
vipWindow.setType(CustomerType.VIP);
vipWindow.start();
//定时器
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable() {
@Override
public void run() {
Integer number=NumberMachine.getInstance().getCommonManager().generateNewManager();
System.out.println(number+" 号 普通 客户等待服务");
}
},
0,
Constants.COMMON_CUSTOMER_TIME,
TimeUnit.SECONDS);
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable() {
@Override
public void run() {
Integer number=NumberMachine.getInstance().getVipManager().generateNewManager();
System.out.println(number+" 号 VIP 客户等待服务");
}
},
0,
Constants.COMMON_CUSTOMER_TIME*6,
TimeUnit.SECONDS);
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable() {
@Override
public void run() {
Integer number=NumberMachine.getInstance().getExpressManager().generateNewManager();
System.out.println(number+" 号 快速 客户等待服务");
}
},
0,
Constants.COMMON_CUSTOMER_TIME*2,//这个地方为什么是2,很绕,绕了好久,
//一秒钟可以进来一个(6/10)的那一类人,那么2秒中可以进来一个(3/10)的那一类人,6秒中可以进来一个(1/10)的那一类人
TimeUnit.SECONDS);
}
}
最后将程序中的所要使用的类型定义成单个类,将服务最大最小时间也封装成一个类
public enum CustomerType {
COMMON,EXPRESS,VIP;
public String toString()
{
switch (this) {
case COMMON:
return "普通";
case EXPRESS:
return "快速";
case VIP:
return name();
}
return null;
}
}
public class Constants {
public static int MAX_SERVICE_TIME=10000;
public static int MIN_SERVICE_TIME=1000;
public static int COMMON_CUSTOMER_TIME=1;
}
总结:这个实战型项目,运用了很多可以java基础知识。java的多线程,要使用同步函数synchronized,来避免多线程下的错误。
在号码机器类中使用了单例模式,让所有的号码都是有同一个号码机器产生的。在服务窗口中通过switch判断号码类型给以不同的
服务。在服务方法中,如果取到要服务的客户,那么为其服务,并记录下服务的时间,没有取到就执行等待后重复start方法,或者
直接执行普通服务的方法。在主类中使用了定时器,每种客户来的速度不同,设置定时器的刷新时间。
同样很巧妙的使用了面相对象编程,java就是一门面相对象编程的语言。这个是以后要多练习的。
复习时看着这个图就能很轻松的写下代码