银行出纳员仿真

xiaoxiao2021-02-28  68

package learn.thread; import java.util.LinkedList; import java.util.PriorityQueue; import java.util.Queue; import java.util.Random; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * 顾客 * <br> * 每个Teller任务在任何时刻都只从输入队列中移除一个Customer * 并且在这个Customer上工作直至完成 因此Customer 在任何时刻 * 都只由一个任务访问 * @author 陈中强 * @Time 2017年7月10日 上午11:40:00 */ class Customer{ /** * final 修饰 对象不会发生变化 只读对象 * 并且不需要同步或者使用volatile */ private final int serviceTime; public Customer(int tm){ serviceTime = tm; } public int getServiceTime(){ return serviceTime; } public String toString(){ return "[Customer:"+serviceTime+"]"; } } /** * 顾客排队 先进先出 队列 * @author 陈中强 * @Time 2017年7月10日 下午4:16:55 */ class CustomerLine extends ArrayBlockingQueue<Customer>{ public CustomerLine(int maxLineSzie) { super(maxLineSzie); } public String toString(){ if(this.size() == 0){ return "Customer Empty"; } StringBuilder result = new StringBuilder(); for(Customer customer : this){ result.append(customer); } return result.toString(); } } /** * 客户队列生成 * @author 陈中强 * @Time 2017年7月10日 下午4:17:49 */ class CustomerGenerator implements Runnable{ private CustomerLine customers; private static Random rand = new Random(47); public CustomerGenerator(CustomerLine cq){ customers = cq; } @Override public void run() { try{ while(!Thread.interrupted()){ TimeUnit.MILLISECONDS.sleep(rand.nextInt(300)); customers.put(new Customer(rand.nextInt(1000))); } }catch(InterruptedException e){ System.out.println("CustomerGenerator interrupted"); } System.out.println("CustomerGenerator terminating"); } } /** * 柜员 * @author 陈中强 * @Time 2017年7月10日 下午4:19:03 */ class Teller implements Runnable,Comparable<Teller>{ private static int counter = 0; private final int id = counter++; private int customersServed = 0;//已经服务的客户 customers served during this shift private CustomerLine customers;//客户队列 private boolean servingCustomerLine = true;//是否正在服务客户 public Teller(CustomerLine cq){ customers = cq; } @Override public void run() { try{ while(!Thread.interrupted()){ Customer customer = customers.take(); TimeUnit.MILLISECONDS.sleep(customer.getServiceTime()); synchronized(this){ customersServed++; while(!servingCustomerLine){ wait(); } } } }catch(InterruptedException e){ System.out.println(this + " interrupted"); } System.out.println(this +" terminating"); } /** * 做其他事 不服务客户了 * @author 陈中强-chen * @Time 2017年7月10日 下午4:24:13 */ public synchronized void dosomethingElse(){ customersServed = 0; servingCustomerLine = false; } /** * 断言 正在服务客户时 * 并唤醒所有线程 * @author 陈中强-chen * @Time 2017年7月10日 下午2:11:06 */ public synchronized void serveCustomerLine(){ assert !servingCustomerLine : "already serving:" + this; servingCustomerLine = true; notifyAll(); } public String toString(){ return "Teller "+ id +" "; } public String shortString(){ return "T"+id; } /** * 比较 已经服务的客户 customersServed * @param other * @return * @see java.lang.Comparable#compareTo(java.lang.Object) * @author 陈中强-chen * @Time 2017年7月10日 下午2:17:55 */ @Override public synchronized int compareTo(Teller other) { return customersServed < other.customersServed ? -1 :(customersServed == other.customersServed ? 0 :1); } } /** * 柜员管理 * @author 陈中强 * @Time 2017年7月10日 下午4:28:10 */ class TellerManager implements Runnable{ private ExecutorService exec; private CustomerLine customers; //优先级队列 头部指向 排序的最小元素 private PriorityQueue<Teller> workingTellers = new PriorityQueue<Teller>(); private Queue<Teller> tellersDoingOtherThings = new LinkedList<Teller>(); private int adjustmentPeriod; private static Random rand = new Random(47); public TellerManager(ExecutorService e,CustomerLine customers,int adjustmentPeriod) { exec = e; this.customers = customers; this.adjustmentPeriod = adjustmentPeriod; Teller teller = new Teller(customers); exec.execute(teller); workingTellers.add(teller); } /** * 调整出纳员数量 * This is actually a control system . By adjusting the number. * you can reveal stability issues in the control mechanism. * If line too long .add anther teller. * @author 陈中强-chen * @Time 2017年7月10日 下午2:58:23 */ public void adjustTellerNumber(){ //如果客户的数量是柜员的两倍多 if(customers.size()/ workingTellers.size() > 2){ //如果有做其他事情的柜员 If tellers are on break or doing another job .bring one back: if(tellersDoingOtherThings.size() > 0){ //从做其他事的 柜员中 调出第一个 Teller teller = tellersDoingOtherThings.remove(); //去服务客户 teller.serveCustomerLine(); //工作中的队列就加了一个人 workingTellers.offer(teller); return; } // Else create(hire) a new teller Teller teller = new Teller(customers); exec.execute(teller); workingTellers.add(teller); return; } // If line is short enough.remove a teller if(workingTellers.size() >1 && customers.size() / workingTellers.size() < 2){ reassignOneTeller(); } // If there is no line . we only need one teller . if(customers.size() == 0){ while(workingTellers.size() > 1){ reassignOneTeller(); } } } /** * 分配出一个出纳员 * Give a teller a different job or a break: * @author 陈中强-chen * @Time 2017年7月10日 下午3:09:15 */ private void reassignOneTeller() { Teller teller = workingTellers.poll(); teller.dosomethingElse(); tellersDoingOtherThings.offer(teller); } @Override public void run() { try { while(!Thread.interrupted()){ TimeUnit.MILLISECONDS.sleep(adjustmentPeriod); adjustTellerNumber(); System.out.println(customers + "{"); for(Teller teller : workingTellers){ System.out.println(teller.shortString() + " "); } System.out.println("}"); } } catch (InterruptedException e) { System.out.println(this + " interrupted"); } System.out.println(this + " terminating"); } public String toString(){ return "TellerManager"; } } /** * 银行出纳员仿真 主函数 * @author 陈中强 * @Time 2017年7月10日 下午5:05:30 */ public class BankTellerSimulation { static final int MAX_LINE_SIZE = 50; static final int ADJUSTMENT_PERIOD = 1000; public static void main(String[] args) throws Exception{ ExecutorService exec = Executors.newCachedThreadPool(); //If line too long .customers will leave; CustomerLine customers = new CustomerLine(MAX_LINE_SIZE); exec.execute(new CustomerGenerator(customers)); // Manager will add and remove tellers as necessary: exec.execute(new TellerManager(exec, customers, ADJUSTMENT_PERIOD)); if(args.length > 0){// Option argument TimeUnit.SECONDS.sleep(new Integer(args[0])); }else{ System.out.println("Press " + "'Enter' to quit"); System.in.read(); } exec.shutdownNow(); } }
转载请注明原文地址: https://www.6miu.com/read-36113.html

最新回复(0)