这个仿真模型包括如下几个对象:
顾客: 随机的时间间隔出现顾客,每个顾客办理业务的时间也是随机。顾客会排队办理业务。
出纳: 每次选取排在最前面的顾客进行服务,服务时间由顾客的业务时间而定。
出纳经理: 每隔一段时间,查看顾客排队的人数,排队的人多就增加出纳窗口,排队人少的话,就减少出纳窗口,让出纳休息。
通过调整这个模型的参数:
1.顾客出现的时间间隔
2.各项业务办理的时间
可以估算出柜台大致需要多少个出纳。
顾客: 随机的时间间隔出现顾客,每个顾客办理业务的时间也是随机。顾客会排队办理业务。
出纳: 每次选取排在最前面的顾客进行服务,服务时间由顾客的业务时间而定。
出纳经理: 每隔一段时间,查看顾客排队的人数,排队的人多就增加出纳窗口,排队人少的话,就减少出纳窗口,让出纳休息。
通过调整这个模型的参数:
1.顾客出现的时间间隔
2.各项业务办理的时间
可以估算出柜台大致需要多少个出纳。
package test.thread;
import static java.lang.System.out;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.TimeUnit;
public class SimulatorTeller {
public static void main(String args[]){
BlockingQueue<Customer> customerQueue=new LinkedBlockingQueue();;
PriorityBlockingQueue<Teller> tellerRestQueue=new PriorityBlockingQueue();
PriorityBlockingQueue<Teller> tellerWorkQueue=new PriorityBlockingQueue();
ExecutorService se=Executors.newCachedThreadPool();
se.execute(new CustomerGenerator(customerQueue));
se.execute(new TellerManager(customerQueue,tellerRestQueue,tellerWorkQueue,se));
}
}
class Customer{
static int count=0;
final int id=count++;
final int serviceTime=(int)(5000* Math.random());
}
class CustomerGenerator implements Runnable{
private BlockingQueue<Customer> customerQueue;
public CustomerGenerator(BlockingQueue<Customer> customerQueue) {
this.customerQueue = customerQueue;
}
public void run() {
try {
while(!Thread.interrupted()){
customerQueue.offer(new Customer());
TimeUnit.MILLISECONDS.sleep((long)(Math.random()*1000));
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class Teller implements Runnable, Comparable<Teller>{
static int count=0;
final int id=count++;
private BlockingQueue<Customer> customerQueue;
private boolean canRest=false;
private int servedCount=0;
public Teller(BlockingQueue<Customer> customerQueue) {
this.customerQueue = customerQueue;
}
public void takeABreak(){
out.println("Teller#"+id+" have served "+servedCount+" customer, take a break now.");
this.canRest=true;
servedCount=0;
}
public synchronized void goBackToWork(){
out.println("Too many customer waiting, Teller#"+id+" go back to work.");
this.canRest=false;
this.notify();
}
public void run() {
try {
while (!Thread.interrupted()) {
Customer c=customerQueue.take();
TimeUnit.MILLISECONDS.sleep(c.serviceTime);
synchronized(this){
servedCount++;
out.println("Teller#"+id+" serverd customer#"+c.id);
if(canRest){
wait();
}
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//serverCount多的Teller优先获得休息权力
public int compareTo(Teller o) {
return this.servedCount < o.servedCount ? 1
: this.servedCount > o.servedCount ? -1 : 0;
}
}
class TellerManager implements Runnable{
private BlockingQueue<Customer> customerQueue;
private PriorityBlockingQueue<Teller> tellerRestQueue;
private PriorityBlockingQueue<Teller> tellerWorkQueue;
private ExecutorService se;
public TellerManager(BlockingQueue<Customer> customerQueue,
PriorityBlockingQueue<Teller> tellerRestQueue,
PriorityBlockingQueue<Teller> tellerWorkQueue, ExecutorService se) {
this.customerQueue = customerQueue;
this.tellerRestQueue = tellerRestQueue;
this.tellerWorkQueue = tellerWorkQueue;
this.se = se;
}
public void run() {
try {
while (!Thread.interrupted()) {
makeAjustMent();
TimeUnit.MILLISECONDS.sleep(2000l);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void makeAjustMent() {
try {
out.println("Customer["+customerQueue.size()+"]/TellerWorker["+tellerWorkQueue.size()+"]/TellerRest["+tellerRestQueue.size()+"]");
if (tellerWorkQueue.size() == 0&&tellerRestQueue.size() == 0) {
assignNewTeller();
} else if (customerQueue.size() / tellerWorkQueue.size() > 2) {
if(tellerRestQueue.size()>0){
Teller t = tellerRestQueue.take();
t.goBackToWork();
tellerWorkQueue.put(t);
}else{
assignNewTeller();
}
}else if (customerQueue.size() / tellerWorkQueue.size() < 2) {
Teller t=tellerWorkQueue.take();
t.takeABreak();
tellerRestQueue.put(t);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void assignNewTeller(){
Teller t = new Teller(customerQueue);
tellerWorkQueue.add(t);
se.execute(t);
}
}