银行出纳员仿真

1 篇文章 0 订阅
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();
    }
}





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值