并发编程 出纳-顾客模型 仿真练习
这个仿真模型包括如下几个对象:
顾客: 随机的时间间隔出现顾客,每个顾客办理业务的时间也是随机。顾客会排队办理业务。
出纳: 每次选取排在最前面的顾客进行服务,服务时间由顾客的业务时间而定。
出纳经理: 每隔一段时间,查看顾客排队的人数,排队的人多就增加出纳窗口,排队人少的话,就减少出纳窗口,让出纳休息。
通过调整这个模型的参数:
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 blocke.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 blocke.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 blocke.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 blocke.printStackTrace();}}private void assignNewTeller(){Teller t = new Teller(customerQueue);tellerWorkQueue.add(t);se.execute(t);}}