---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IO开发S</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------
感觉比交通灯的复杂一些.
这个系统主要分成3个部分来做,分别是,号码管理器,号码产生的机器和服务窗口三个部分.号码管理器( NumberManager)的主要做作用是产生新的号码和取号.里面涉及多线程的安全问题,因此要注意对共有资源语句的同步.号码产生的机器的主要作用是管理3个不同客户对象的号码,要保证它的唯一性,所以将它设计成单例模式.服务窗口(ServiceWindow)针对三个不同的串口进行服务,里面涉及的主要是取号及服务时间的问题.
一.号码管理器( NumberManager)的设计
有 2个方法,产生新号和取号的操作,以为这2个线程同时对号码的资源进行操作,为避免安全问题,将方法同步.代码如下:
import java.util.ArrayList;
import java.util.List;
public class NumberManager { //负责对号码的操作
private List number = new ArrayList(); //存储已经办理的号码
private int LastNumber = 0;
public synchronized Integer generateNumber(){ //产生新号的方法
number.add(++LastNumber); //将所有号码添进集合,方便以后取出
return ++LastNumber; //返回新的号码
}
public synchronized Integer fetchNumber(){ //取号方法
if (number.size()>0) {
return (Integer)number.remove(0); //取到号
}else
return null;
}
}
二.号码产生的机器
号码的产生是由三个不同的号码管理器产生的,因此将他们三个封装在一个对象里,为保证它的唯一性,将其单例化,代码如下:
public class NumberMachine { //产生三个不同客户的对象
private NumberManager commonManage = new NumberManager();
private NumberManager rapidManage = new NumberManager();
private NumberManager VIP = new NumberManager();
public NumberManager getCommonManage() {
return commonManage;
}
public NumberManager getRapidManage() {
return rapidManage;
}
public NumberManager getVIP() {
return VIP;
}
//因为只可能有一个NumberMachine,所以将它设计成单例模式
private NumberMachine(){}
private static NumberMachine numberMachine = new NumberMachine();
public static NumberMachine getInstance(){
return numberMachine;
}
}
三.服务窗口的设计
怕把自己又绕晕了,所以暂时没有对其优化.这是分别对这三类客户进行的服务,
首先,客户类型是固定的,所以 将它设计为枚举类型,代码如下:
public enum ClientType {
COMMONCLIENT,REPIDCLIENT,VIP;
public String toString(){
switch(this){
case COMMONCLIENT:
return "普通";
case REPIDCLIENT:
return "快速";
case VIP:
return "VIP";
}
return null;
}
}
里面涉及到的时间的常量也单独建立一个类,
public class Constant {
public static int MAX_SERVE_TIME = 10000;
public static int Min_SERVE_TIME = 1000;
public static int COMMON_CUSTOMER_INTEVAL_TIME = 1;
}
开始取号判断,分别对取号的情况进行处理,如取到号与没有取到号的情况.代码如下:
import java.util.Random;
import java.util.concurrent.Executors;
public class ServiceWindow {
private ClientType type = ClientType.COMMONCLIENT; //客户类型
private int windowId = 1; //窗口号
public void setType(ClientType type) {
this.type = type;
}
public void setWindowId(int windowId) {
this.windowId = windowId;
}
public void start(){
Executors.newSingleThreadExecutor().execute(new Runnable(){
@Override
public void run() {
while(true){
switch(type){
case COMMONCLIENT:
commonServe();
break;
case REPIDCLIENT:
repidClient();
break;
case VIP:
VIPServe();
break;
}
}
}
private void VIPServe() {
String WindowName = "第"+windowId+"号"+type+"窗口";
System.out.println(WindowName+"正在获取服务");
Integer number = NumberMachine.getInstance().getVIP().fetchNumber();//取号
if (number!=null) {
long start = System.currentTimeMillis();
long end = System.currentTimeMillis();
long costTime = end - start;
int maxRandom = Constant.MAX_SERVE_TIME-Constant.Min_SERVE_TIME;
int serveTime = new Random().nextInt(maxRandom)+1+Constant.Min_SERVE_TIME;
try {
Thread.sleep(serveTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(WindowName+"为第"+number+"个"+"VIP客户服务:耗时"+costTime/1000);
}else{
System.out.println(WindowName+"获取服务失败,为普通客户服务");
commonServe();
}
}
private void repidClient() {
String WindowName = "第"+windowId+"号"+type+"窗口";
System.out.println(WindowName+"正在获取任务");
Integer number = NumberMachine.getInstance().getRapidManage().fetchNumber();
if (number!=null) {
long start = System.currentTimeMillis();
long end = System.currentTimeMillis();
try {
Thread.sleep(Constant.Min_SERVE_TIME);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long costTime = end - start;
System.out.println(WindowName+"为第"+number+"个"+"快速客户服务:耗时"+costTime/1000);
}else{
System.out.println(WindowName+"没有获取到任务,为普通客户服务");
commonServe();
}
}
private void commonServe() {
String WindowName = "第"+windowId+"号"+type+"窗口";
System.out.println(WindowName+"正在获取任务");
Integer number = NumberMachine.getInstance().getCommonManage().fetchNumber();
if (number!=null) {
long start = System.currentTimeMillis();
int maxRandom = Constant.MAX_SERVE_TIME-Constant.Min_SERVE_TIME;
int serveTime = new Random().nextInt(maxRandom)+1+Constant.Min_SERVE_TIME;
try {
Thread.sleep(serveTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long end = System.currentTimeMillis();
long costTime = end-start;
System.out.println(WindowName+"为第"+number+"个"+"普通客户服务:耗 时"+costTime/1000);
}else{
System.out.println(WindowName+"没有取到任务,先休息一秒钟");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
}
}
最后是对它进行测试,这是三个线程同时取号,因此开了3条线程,都在线程池里完成,注意处理给定的一些条件,如6个窗口,其中4个是普通客户窗口,一个快速窗口可一个VIP窗口,
VIP客户 :普通客户 :快速客户 = 1 :6 :3等,具体代码如下:
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
public class Test {
private static Logger logger = Logger.getLogger("edu.csdn.bankqueue");
public static void main(String[] args) {
for (int i = 0; i < 5; i++) { //四个普通窗口
ServiceWindow commonWindow = new ServiceWindow();
commonWindow.setWindowId(i);
commonWindow.start();
}
ServiceWindow repidWindow = new ServiceWindow(); //一个快速窗口
repidWindow.setType(ClientType.REPIDCLIENT);
repidWindow.start();
ServiceWindow VIP = new ServiceWindow(); //一个VIP窗口
VIP.setType(ClientType.VIP);
VIP.start();
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable(){
@Override
public void run() {
Integer number = NumberMachine.getInstance().getCommonManage().generateNumber();
System.out.println(number+"普通客户正在等待服务");
}
},
0,
Constant.COMMON_CUSTOMER_INTEVAL_TIME,
TimeUnit.SECONDS);
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable(){
@Override
public void run() {
Integer number = NumberMachine.getInstance().getRapidManage().generateNumber();
System.out.println(number+"快速客户正在等待服务");
}
},
0,
Constant.COMMON_CUSTOMER_INTEVAL_TIME*3, //为什么是*2
TimeUnit.SECONDS);
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable(){
@Override
public void run() {
Integer number = NumberMachine.getInstance().getVIP().generateNumber();
System.out.println(number+"VIP客户正在等待服务");
}
},
0,
Constant.COMMON_CUSTOMER_INTEVAL_TIME*6,
TimeUnit.SECONDS);
}
}
这个程序对我来说还是比较复杂的,经过反复的调试,其中错误很多,不仅需要思路,更需要细心跟耐心,
---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IO开发S</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------