第二十一章:并发(下)

来源:互联网 发布:淘宝美工基础教程 编辑:程序博客网 时间:2024/06/01 19:53

新类库中的构件

CountDownLatch

  • 可以向CountDownLatch对象设置一个初始计数值,任何对象在这个对象上调用await()方法都将阻塞,直至这个计数值为0(如果一开始就是0那就不用等待)。我们通过其他任务在这个对象上调用countDown()来缩小这个计数值(最多减到0)。这个构件的意义就是设置一些任务必须在n个任务都完成的情况下才可以执行。
import java.util.Random;import java.util.concurrent.CountDownLatch;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class CountDownLatchDemo {    static final int SIZE = 100;    public static void main(String args[]) throws Exception {        ExecutorService exec = Executors.newCachedThreadPool();        CountDownLatch latch = new CountDownLatch(SIZE);        for (int i=0; i<10; i++) {            exec.execute(new WaitingTask(latch));        }        for (int i=0; i<SIZE; i++) {            exec.execute(new TaskPortion(latch));        }        System.out.println("Launched all tasks");        exec.shutdown();    }}class TaskPortion implements Runnable {    private static int counter = 1;    private static Random rand = new Random(47);    private final int id = counter++;    private final CountDownLatch latch;    public TaskPortion(CountDownLatch latch) {        this.latch = latch;    }    @Override    public void run() {        try {            Thread.sleep(rand.nextInt(2000));//模拟一个任务需要时间去完成            System.out.println(this + "completed");            latch.countDown();            System.out.println(latch.getCount());        } catch (InterruptedException e) {}    }    public String toString() {        return String.format("%-3d ", id);    }}class WaitingTask implements Runnable {    private static int counter = 1;    private final int id = counter++;    private final CountDownLatch latch;    public WaitingTask(CountDownLatch latch) {        this.latch = latch;    }    @Override    public void run() {        try {            latch.await();            System.out.println("Latch barrier passed for " + this);        } catch (InterruptedException e) {            System.out.println(this + "interrupted");        }    }    public String toString() {        return String.format("WaitingTask %-3d ", id);    }}
  • 程序运行后,10个WaitingTask任务将等待,直到100个TaskPortion全部执行完毕再开始执行。

CyclicBarrier

  • CyclicBarrier适用于你希望创建一组任务,它们并行执行,然后在进行下一个步骤之前等待,直至所有任务都完成。它使得所有的并行任务都将在栅栏处列队,因此可以一致地向前运动。它与CountDownLatch的区别是,后者是只触发一次的事件,而它可以多次重用。下面是我模仿书上赛马的程序写的一个关于加载的程序:
import java.util.ArrayList;import java.util.List;import java.util.Random;import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** * 模拟LOL要10个人才能开始游戏 * 每次必须满10个人一起加载一次,当加载量都为100时,游戏开始 */public class PlayGame {    public static ExecutorService exec = Executors.newCachedThreadPool();    public static List<Player> players = new ArrayList<Player>();    public static CyclicBarrier barrier = new CyclicBarrier(10, new StartGame(players));    static {        for (int i=0; i<10; i++) {            Player p = new Player();            players.add(p);            System.out.println("player" + p.id + " 准备进入游戏");        }    }    public static void main(String args[]) {        for (int i=0; i<10; i++)            exec.execute(new LoadGame(players.get(i), barrier));    }}class Player {    private static int counter = 1;    private int percentage = 0;    public final int id = counter++;    public void addPercentage(int nextInt) {        percentage += nextInt;        System.out.println("player" + id + " 加载了" + percentage + "%");    }    public int getPercentage() {return percentage;}}class LoadGame implements Runnable {    private static Random rand = new Random(47);    private final CyclicBarrier barrier;    private final Player player;    public LoadGame(Player player, CyclicBarrier barrier) {        this.player = player;        this.barrier = barrier;    }    @Override    public void run() {        try {            while (!Thread.interrupted()) {                if (player.getPercentage() < 96) {                    player.addPercentage(rand.nextInt(5) + 1);//1~5                } else {                    player.addPercentage(100 - player.getPercentage());                }                barrier.await();            }        } catch (InterruptedException e) {            System.out.println();        } catch (BrokenBarrierException e) {            throw new RuntimeException(e);        }        System.out.println("player" + player.id + " 开始游戏");    }}class StartGame implements Runnable {    private List<Player> players;    public StartGame(List<Player> players) {        this.players = players;    }    @Override    public void run() {        System.out.println("服务器集中加载一次完毕!");        int i = 0;        for (Player player : players) {            if (player.getPercentage() < 100) {                break;            }            i++;        }        if (i == players.size()) {            System.out.println("比赛开始!");            PlayGame.exec.shutdownNow();        }    }}

DelayQueue

  • 这个是一个延迟队列,他也是线程安全的,存放的泛型类型必须实现Delayed接口。当其实它和优先级队列挺像的,下面是一个例子:
import java.util.*;import java.util.concurrent.*;class DelayedTask implements Runnable, Delayed {    private final long delay;    private final long runtime;    private final int id;    public DelayedTask(int id, long delay) {        this.id = id;        this.delay = delay;        this.runtime = System.currentTimeMillis() + delay;    }    @Override    public int compareTo(Delayed o) {        DelayedTask t = (DelayedTask) o;        long result = this.runtime -  t.runtime;        if (result > 0) return 1;        else if (result < 0) return -1;        else return 0;    }    @Override    public long getDelay(TimeUnit unit) {        return unit.convert(runtime - System.currentTimeMillis(),                TimeUnit.MILLISECONDS);    }    @Override    public void run() {        System.out.println(id + " run! delay=" + delay);    }}class DelayedTaskConsumer implements Runnable {    private DelayQueue<DelayedTask> q;    public DelayedTaskConsumer(DelayQueue<DelayedTask> q) {        this.q = q;    }    @Override    public void run() {        try {            while (!Thread.interrupted()) {                q.take().run();//只是run 没有start            }        } catch (InterruptedException e) {}        finally {            System.out.println("finish!");        }    }}public class DelayQueueDemo {    public static void main(String[] args) throws Exception {        Random rand = new Random(47);        ExecutorService exec = Executors.newCachedThreadPool();        DelayQueue<DelayedTask> queue =  new DelayQueue<DelayedTask>();        for (int i=0; i<20; i++) {            queue.put(new DelayedTask(i + 1, rand.nextInt(5000)));        }        exec.execute(new DelayedTaskConsumer(queue));        Thread.sleep(5000);        exec.shutdownNow();    }}

PriorityBlockingQueue

  • 如果你看过之前集合中的PriorityQueue, 再结合BlockingQueue的用法,我想这个可以省略了。

ScheduledExecutor

  • 这是一种定时器的方式,类似于js中的setTimeout()setInterval()。直接看例子吧。
import java.text.SimpleDateFormat;import java.util.Date;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.ScheduledThreadPoolExecutor;import java.util.concurrent.TimeUnit;public class ScheduleThreadPoolDemo {    private static SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss SSS");    public static void main(String args[]) {        ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(5);        exec.schedule(new Mission(), 1000, TimeUnit.MILLISECONDS);        //这个是根据上一次开始时间去延迟1000毫秒        exec.scheduleAtFixedRate(new Mission(), 2000, 1000, TimeUnit.MILLISECONDS);        //这个是根据上一次结束时间去延迟1000毫秒        exec.scheduleWithFixedDelay(new Mission(), 3000, 1000, TimeUnit.MILLISECONDS);        //用法一致 其实返回的是同一种类型        //ScheduledExecutorService exec2 = Executors.newScheduledThreadPool(5);        //exec2.schedule(command, delay, unit)        //exec2.scheduleAtFixedRate(command, initialDelay, period, unit)        //exec2.scheduleWithFixedDelay(command, initialDelay, delay, unit)    }    static class Mission implements Runnable {        private static int count = 0;        private final int id = ++count;        @Override        public void run() {            System.out.println(id + " run in:" +                     sdf.format(new Date(System.currentTimeMillis())));        }    }}

Semaphore

  • 正常的锁(locks或synchronized)在任何时刻都只允许一个任务访问一项资源。而计数信号量允许n个任务同时访问这个资源(这个资源可能是一个对象池)。
import java.lang.reflect.Array;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;public class SemaphoreDemo {    private static final int poolsize = 3;    public static void main(String args[]) throws Exception {        Pool<TestObj> pool = new Pool<TestObj>(TestObj.class, poolsize);        ExecutorService exec = Executors.newCachedThreadPool();        for (int i=0; i<poolsize; i++) {            exec.execute(new Hold<TestObj>(pool, (i + 1) * 1000));        }         for (int i=0; i<poolsize; i++) {            exec.execute(new Hold<TestObj>(pool, 500));        }        exec.shutdown();    }}class Hold<T> implements Runnable {    private static int count;    private final int id = ++count;    private final Pool<T> pool;    private final long time;    public Hold(Pool<T> pool, long time) {        this.pool = pool;        this.time = time;    }    public void run() {        try {            T task = pool.checkOut();            System.out.println("Thread" + id + " get: " + task);            Thread.sleep(time);            System.out.println("Thread" + id + " release: " + task);            pool.checkIn(task);            System.out.println("Thread" + id + " release success!");        } catch (InterruptedException e) {            e.printStackTrace();        }    }}class TestObj {    private static int count;    private final int id = ++count;    public int getId() {        return id;    }    public String toString() {        return "resourceId:" + id;    }}class Pool<T> {    private Semaphore available;    private int size;    private T[] data;    private boolean[] checkOut;    @SuppressWarnings("unchecked")    public Pool(Class<T> clazz, int size) throws InstantiationException, IllegalAccessException {        available = new Semaphore(size, true);        this.size = size;        checkOut = new boolean[size];        data = (T[]) Array.newInstance(clazz, size);        for (int i=0; i<size; i++) {            data[i] = clazz.newInstance();        }    }    public T checkOut() throws InterruptedException {        available.acquire();//请求一个许可证,如果没有则等待。        return getItem();    }    public boolean checkIn(T x) throws InterruptedException {        if (releaseItem(x)) {            available.release();//释放一个许可证            return true;        }        return false;    }    private synchronized T getItem() {        for (int i=0; i<size; i++) {            if (!checkOut[i]) {                checkOut[i] = true;                return (T) data[i];            }        }        return null;    }    private synchronized boolean releaseItem(T x) {        for (int i=0; i<size; i++) {            if (data[i] == x) {                if (checkOut[i]) {                    checkOut[i] = false;                    return true;                }                return false;            }        }        return false;    }}--------------运行结果:Thread1 get: resourceId:1Thread2 get: resourceId:2Thread3 get: resourceId:3Thread1 release: resourceId:1Thread1 release success!Thread4 get: resourceId:1Thread4 release: resourceId:1Thread4 release success!Thread5 get: resourceId:1Thread2 release: resourceId:2Thread2 release success!Thread6 get: resourceId:2Thread5 release: resourceId:1Thread5 release success!Thread6 release: resourceId:2Thread6 release success!Thread3 release: resourceId:3Thread3 release success!

Exchanger

  • Exchanger是在两个任务之间交换对象的栅栏。他们各自拥有一个对象,调用exchange()后(可能进入阻塞,等待对方调用这个方法),会得到对方的对象。Exchanger的应用场景是:一个任务在创建对象,这些对象的生产代价很高昂。而另外一个任务在消费这些对象(然后将空容器返回给生产者)。听起来和普通的生产者消费者差不多,区别就是可以在消费这个对象的同时创建新的对象(因代价高昂需尽早创建,且因为调用exchange()会阻塞,也不必担心浪费空间)。可以想象这么一个场景:一共有两个水桶,一个人负责在井边打水,一个人负责拿着装满水的桶去装进自家水库。要是只有一个水桶,打水的和倒水的难免得互相等待。如果有两个桶,倒水的每次只要将空桶交给打水的,然后直接拿走装满水的桶,那么就可以使效率提高。
import java.util.List;import java.util.concurrent.*;public class ExchangerDemo {    public static void main(String args[]) {        Exchanger<List<Integer>> changer = new Exchanger<List<Integer>>();        ExecutorService exec = Executors.newCachedThreadPool();        exec.execute(new ExchangerProducer(changer));        exec.execute(new ExchangerConsumer(changer));        exec.shutdown();    }}class ExchangerProducer implements Runnable {    //这个类型可以在遍历的时候,remove。因为是交换对象,所以生产者的类型一般都和消费者一致    private List<Integer> holder = new CopyOnWriteArrayList<>();    private int begin = 0;    private Exchanger<List<Integer>> changer;    public ExchangerProducer(Exchanger<List<Integer>> changer) {        this.changer = changer;    }    @Override       public void run() {        try {            while (!Thread.interrupted()) {                for (int i=begin; i<begin+10; i++) {                    holder.add(i);                }                begin = begin + 10;                System.out.println("producer 前 " + holder);                holder = changer.exchange(holder);                System.out.println("producer 后 " + holder);                Thread.sleep(1000);            }        } catch (InterruptedException e) {            e.printStackTrace();        }    }}class ExchangerConsumer implements Runnable {    private List<Integer> holder = new CopyOnWriteArrayList<>();//这个类型可以在遍历的时候,remove    private Exchanger<List<Integer>> changer;    public ExchangerConsumer(Exchanger<List<Integer>> changer) {        this.changer = changer;    }    @Override       public void run() {        try {            while (!Thread.interrupted()) {                System.out.println("consumer 前 " + holder);                holder = changer.exchange(holder);                System.out.println("consumer 后 " + holder);                for (Integer i : holder) {                    //holder.remove(i);//注释掉可以看到交换场景                }            }        } catch (InterruptedException e) {            e.printStackTrace();        }    }}

仿真

银行出纳员仿真

  • 看这个名字差不多就知道是什么用处,代码有注释。期间遇到了怪异的问题(出队不是最大值),后来看了看以前的文章就明白了。
import java.util.*;import java.util.concurrent.*;public class BankTellerSimulation {    private static final int MAX_LINE_SIZE = 50;    private static final int ADJUSTMENT_PERIOD = 1000;    public static void main(String args[]) throws Exception {        ExecutorService exec = Executors.newCachedThreadPool();        CustomerLine customers = new CustomerLine(MAX_LINE_SIZE);        exec.execute(new CustomerGenerator(customers));        exec.execute(new TellerManager(exec, customers, ADJUSTMENT_PERIOD));        System.in.read();        exec.shutdownNow();    }}//顾客class Customer {    private final int serviceTime;//此值模拟用户的服务时间    public Customer(int st) {        serviceTime = st;    }    public int getServiceTime() {        return serviceTime;    }    public String toString() {        return "[" + serviceTime + "]";    }}//排号队伍class CustomerLine extends ArrayBlockingQueue<Customer> {    public CustomerLine(int capacity) {        super(capacity);    }    public String toString() {        if (isEmpty()) {            return "[Empty]";        }        StringBuilder result = new StringBuilder();        for (Customer cus : this) {            result.append(cus);        }        return result.toString();    }}//模拟有顾客来办业务class CustomerGenerator implements Runnable {    private static Random random = new Random(47);    private CustomerLine customers;    public CustomerGenerator(CustomerLine cl) {        customers = cl;    }    @Override    public void run() {        try {            while (!Thread.interrupted()) {                Thread.sleep(random.nextInt(300));                //不定期的来客户,其服务时间也不定                customers.put(new Customer(random.nextInt(1000)));            }        } catch (InterruptedException e) {            System.out.println("CustomerGenerator 程序中断");        }        System.out.println("CustomerGenerator 程序停止");    }}//出纳员服务线程class Teller implements Runnable, Comparable<Teller>{    private static int counter = 0;    private final int id = counter++;    private int customerServed = 0;//已服务人数    private CustomerLine customers;    private boolean servingCustomerLine = true;    public Teller(CustomerLine cl) {        customers = cl;    }    @Override    public void run() {        try {            while (!Thread.interrupted()) {                Customer customer = customers.take();//呼叫客户,如果没有则阻塞                Thread.sleep(customer.getServiceTime());//模拟进行服务                //在服务期间TellerManager线程可能判断出此时不再需要那么多人了,servingCustomerLine被置为false                synchronized (this) {                    customerServed++;//服务人数加1                    //如果此时TellerManager线程已经允许我们释放自己,那么我们就wait()。                    //用while是因为唤醒的可能是别人而不是自己                    while (!servingCustomerLine)                        wait();//wait期间TellerManager线程可能又将其设置为true                }            }        } catch (InterruptedException e) {            System.out.println("Teller 程序中断");        }        System.out.println("Teller 程序停止");    }    //没人来了就等待,或者说去做别的事情去    public synchronized void doSomethingElse() {        //customerServed = 0;//书上有这句代码,我觉得没有必要,因为讲道理是可以累积的        servingCustomerLine = false;//将这个出纳员的状态调整为休息状态        //吃饭聊天打豆豆...爱干嘛干嘛    }    //有人来了就开始服务    public synchronized void serveCustomerLine() {        assert !servingCustomerLine : "服务已经在运行!:" + this;        servingCustomerLine = true;        notifyAll();    }    //用于线程资源合理分配,干活多的出纳员优先出队去干别的事情。比较期间不允许对customerServed进行修改,所以是synchronized的。    public synchronized int compareTo(Teller o) {        return customerServed - o.customerServed;    }    //出纳员编号    public String toString() {        return "T" + id + "(" + customerServed + ")";    }}//出纳员控制系统class TellerManager implements Runnable {    private ExecutorService exec;    private CustomerLine customers;    //了解PriorityQueue的应该知道,当poll或者offer一个值时,它并不会遍历所有的队列值    //此处书上使用PriorityQueue是不对的,因为customerServed在中途进行了变化,为了使结果正确我将重写poll方法。    //private PriorityQueue<Teller> workingTellers = new PriorityQueue<Teller>();    private PriorityQueue<Teller> workingTellers = new MyPriorityQueue<Teller>();    //这个队列也不能这么写,也应该选择最小的出来,不过因为这个队列里的customerServed不会变化,所以可以直接使用PriorityQueue    //其实就算改成PriorityQueue也不是特别严谨,要注意到customerServed++基本上是在放入队列后发生的。不过最多差1位,关系不是很大    //这里也体现了要想正确使用并发编程真的很难    //private Queue<Teller> tellerDoingOhterThings = new LinkedList<Teller>();    private Queue<Teller> tellerDoingOhterThings = new PriorityQueue<Teller>();    private int adjustmentPeriod;//调整时间间隔    public TellerManager(ExecutorService e,            CustomerLine cl, int adjustmentPeriod) {        exec = e;        customers = cl;        this.adjustmentPeriod = adjustmentPeriod;        newOneTeller();    }    public void adjustTellerNumber() {        //如果顾客太多了,就增加一个出纳员        if (customers.size() / workingTellers.size() > 2) {            if (tellerDoingOhterThings.size() > 0) {                Teller teller = tellerDoingOhterThings.poll();//选出一个最小值                teller.serveCustomerLine();//从空闲队列中取出一个出纳员进行服务,必须持有teller的锁                workingTellers.offer(teller);                return;            }            newOneTeller();            return;        }        //如果工作的人太多了,就释放一个出纳员        if (workingTellers.size() > 1 && customers.size() / workingTellers.size() < 2) {            reassingOneTeller();        }        //如果没有要服务的客户,则递减到一个出纳员        if (customers.size() == 0) {            while (workingTellers.size() > 1) {                reassingOneTeller();            }        }    }    //分配一个出纳员    private void newOneTeller() {        Teller teller = new Teller(customers);        exec.execute(teller);        workingTellers.add(teller);    }    //释放一个出纳员    private void reassingOneTeller() {        Teller teller = workingTellers.poll();//使用了重写的方法,选出了一个最大值        teller.doSomethingElse();//必须持有teller的锁        tellerDoingOhterThings.offer(teller);    }    @Override    public void run() {        try {            while (!Thread.interrupted()) {                Thread.sleep(adjustmentPeriod);                adjustTellerNumber();//因为只有一个线程,所以不需要加锁                System.out.print(customers + " {工作中: ");                for (Teller teller : workingTellers) {                    System.out.print(teller + " ");                }                System.out.print(", 休息中: ");                for (Teller teller : tellerDoingOhterThings) {                    System.out.print(teller + " ");                }                System.out.println("}");            }        } catch (InterruptedException e) {            System.out.println("TellerManager 程序中断");        }        System.out.println("TellerManager 程序结束");    }}//修改poll方法的优先级队列class MyPriorityQueue<T> extends PriorityQueue<T> {    @Override    public T poll() {        if (isEmpty()) return null;        T[] data = (T[]) toArray();        T max = data[0];        for (int i = 1; i < data.length; i++) {            if (((Comparable<T>) max).compareTo(data[i]) < 0) {                max = data[i];            }        }        remove(max);        return max;    }}

饭店仿真

import java.util.*;import java.util.concurrent.*;public class RestaurantWithQueues {    public static void main(String[] args) throws InterruptedException {        ExecutorService exec = Executors.newCachedThreadPool();        Restaurant rest = new Restaurant(exec, 5, 2);//5个小二,两个厨师        exec.execute(rest);//开业啦        Thread.sleep(10000);//开十秒就关门了        exec.shutdownNow();//所有人都赶出去,最可怕的是连厨师小二都不让干活了    }}//可以假想成一份菜单,不过是一份菜的指派菜单class Order {    private static int counter = 0;    private final int id = counter++;    private final Customer customer;//顾客    private final WaitPerson waitPerson;//服务的小二    private final Food food;//所需的菜肴    public Order(Customer customer, WaitPerson waitPerson, Food food) {        this.customer = customer;        this.waitPerson = waitPerson;        this.food = food;    }    public Food item() {        return food;    }    public Customer getCustomer() {        return customer;    }    public WaitPerson getWaitPerson() {        return waitPerson;    }    public String toString() {        return "Order: " + id + " item: " + food +                 " for: " + customer + " served by: " + waitPerson;    }}//可以假想成一份成品菜肴,可以吃的那种class Plate {    private final Order order;//对应的菜单    private final Food food;//可以吃的菜肴,这里用枚举类代替    public Plate(Order order, Food food) {        this.order = order;        this.food = food;    }    public Order getOrder() {        return order;    }    public Food getFood() {        return food;    }    public String toString() {        return food.toString();    }}//顾客 线程,任务是给小二下单,然后等待小二送来菜肴class Customer implements Runnable {    private static int counter = 0;    private final int id = counter++;    private final WaitPerson waitPerson;//该服务的小二    private static Random rand = new Random(47);    private SynchronousQueue<Plate> plateSetting =            new SynchronousQueue<Plate>();//只有take和put同时完成后,才能进行下次take()和put(),否则任一操作都会阻塞    public Customer(WaitPerson wp) {        waitPerson = wp;    }    public void deliver(Plate p) throws InterruptedException {        plateSetting.put(p);//从小二的手中接过菜肴(put->take 组成一个过程)    }    @Override    public void run() {        Food[] foods = Food.choose();//顾客随机选取了一组菜肴        System.out.println(this + "下单:" + Arrays.toString(foods));        try {            if (!Thread.interrupted())  {                for (Food food : foods) {                    waitPerson.placeOrder(this, food);//一个一个上                    System.out.println(this + "eating " + plateSetting.take());//等待直到 从小二的手中接过菜肴(put->take组成一个过程)。                }            }        } catch (InterruptedException e) {            System.out.println(this + "waiting 中断");        }        System.out.println(this + "吃完了");    }    public String toString() {        return "Customer " + id + " ";    }}//小二 线程,任务是拿出已经做好并且是分发给自己的菜肴,然后送给这个顾客class WaitPerson implements Runnable {    private static int counter = 0;    private final int id = counter++;    private final Restaurant restaurant;    BlockingQueue<Plate> filledOrders =             new LinkedBlockingQueue<Plate>();//小二收到的已经完成的菜肴    public WaitPerson(Restaurant r) {        restaurant = r;    }    public void placeOrder(Customer cust, Food food) {        try {            restaurant.orders.put(new Order(cust, this, food));//添加一份新订单        } catch (InterruptedException e) {            System.out.println(this + " placeOrder 中断");        }    }    public void run() {        try {            while (!Thread.interrupted()) {//压榨他!不许休息                Plate plate = filledOrders.take();//拿出包装好的菜肴                System.out.println(this + "received " + plate                         + " delivering to " + plate.getOrder().getCustomer());//准备丢给那个顾客                plate.getOrder().getCustomer().deliver(plate);//让顾客接收这个菜肴            }        } catch (InterruptedException e) {            System.out.println(this + " 中断");        }        System.out.println(this + " 结束");    }    public String toString() {        return "WaitPerson " + id + " ";    }}//厨师 线程,任务是从订单队列中拿出订单(Order),做完(Plate)并丢给相应的小二class Chef implements Runnable {    private static int counter = 0;    private final int id = counter++;    private final Restaurant restaurant;    private static Random rand = new Random(47);    public Chef(Restaurant r) {        restaurant = r;    }    public void run() {        try {            while (!Thread.interrupted()) {//压榨他!不许休息                Order order = restaurant.orders.take();//厨师从菜单中拿出Order,也就是订单                Food item = order.item();//知道要做什么菜                Thread.sleep(rand.nextInt(500));//假设花的时间不定                Plate plate = new Plate(order, item);//成品菜肴完成了                order.getWaitPerson().filledOrders.put(plate);//丢给这个小二            }        } catch (InterruptedException e) {            System.out.println(this + " 中断");        }        System.out.println(this + " 结束");    }    public String toString() {        return "Chef " + id + " ";    }}//饭店 线程 负责接待顾客,分配小二class Restaurant implements Runnable {    private List<WaitPerson> waitPersons = new ArrayList<WaitPerson>();    private List<Chef> chefs = new ArrayList<Chef>();    private ExecutorService exec;    private static Random rand = new Random(47);    BlockingQueue<Order> orders =             new LinkedBlockingQueue<Order>();//相当于订单表    public Restaurant(ExecutorService exec, int nWaitPersons, int nChefs) {        this.exec = exec;        for (int i = 0; i < nWaitPersons; i++) {            WaitPerson waiter = new WaitPerson(this);            waitPersons.add(waiter);            exec.execute(waiter);        }        for (int i = 0; i < nChefs; i++) {            Chef chef = new Chef(this);            chefs.add(chef);            exec.execute(chef);        }    }    @Override    public void run() {        try {            while (!Thread.interrupted()) {//我就是不关门                WaitPerson wp = waitPersons.get(rand.nextInt(waitPersons.size()));//随机选取一个小二                Customer c = new Customer(wp);//假设来了一个客户,并把这个客户分给这个小二                exec.execute(c);//让这个客户自行下单                Thread.sleep(100);//模拟0.1秒来个客户            }        } catch (InterruptedException e) {            System.out.println("Restaurant 中断");        }        System.out.println("Restaurant 结束");    }}enum Food {    南汇水蜜桃, 三林糖酱瓜, 佘山兰笋, 松江回鳃鲈, 枫泾西蹄, 城隍庙五香豆, 崇明金瓜, 南桥乳腐, 高桥松饼, 嘉定大白蒜;    private static Random rand = new Random(47);    public static Food[] choose() {        Food[] allfoods = values();        int count = allfoods.length;//10        for (int i = 0; i < count - 1; i++) { //打乱顺序            int index = rand.nextInt(count);            Food temp = allfoods[i];            allfoods[i] = allfoods[index];            allfoods[index] = temp;        }        int need = rand.nextInt(allfoods.length / 2) + 1;        Food[] foods = new Food[need];        int beginIndex = rand.nextInt(count - need + 1);        System.arraycopy(allfoods, beginIndex, foods, 0, need);        return foods;    }}

分发工作

性能调优

比较各类互斥技术

免锁容器

乐观锁

比较各类Map实现

乐观加锁

ReadWriteLock

活动对象

小结

  • 还有这么多的内容,我就不写了。。想开启下一本书,这个就先这样吧。以后想起来了再回来更新。
原创粉丝点击