wait()、notify()、notifyAll()方法的理解

wait()表示把线程挂起,挂起的时候会自动释放锁。

notify() 随机的选择一个在指定对象上挂起的线程激活。

notifyAll() 激活指定对象上挂起的所有线程

条件队列:一组等待线程集合,能够通过某种方式来等待对应的条件为真。条件队列中的元素是一个正在等待相关条件的线程。

    通过条件队列构建高可响应的状态依赖类,条件等待存在三元关系 加锁、wait、一个条件谓词(包含多个状态变量) ,状态变量由一个锁保护

     在测试条件谓语之前必须先获得对象的锁。锁对象和条件队列对象(即调用wait()和notify()方法的对象)必须是同一个对象。

如下实现自定义有界缓存实现

     基类代码

package com.lifeStudy.algorith;

public abstract class BaseBoundedBuffer<V> {

    private final V[] buf;
    private int tail;
    private int head;
    private int count;

    protected BaseBoundedBuffer(int capacity) {
        //还可以通过直接new Object[]数组,等到需要具体化时候才 强制转换单个元素
        buf = (V[]) new Object[capacity];//泛型擦除,其实就是(Object[])转换
    }


    protected synchronized final void doPut(V v) {
        buf[tail] = v;
        if (++tail == buf.length) {
            tail = 0;
        }
        count++;
    }

    protected synchronized final V doTake() {
        V rs = buf[head];
        buf[head] = null;
        if (++head == buf.length) {
            head = 0;
        }
        count--;
        return rs;
    }

//下面是两个状态变量,队列是否满;队列是否为空 通过内置锁对象this
public synchronized final boolean isFull() { return count == buf.length; } public synchronized final boolean isEmpty() { return count == 0; } }

 

通过wait()实现条件队列

package com.lifeStudy.algorith;


public class BoundedBuffer<V> extends BaseBoundedBuffer<V> {//条件队列

    protected BoundedBuffer(int capacity) {
        super(capacity);
    }

    public synchronized void put(V v) throws InterruptedException {

        while (isFull()) {
            System.out.println(Thread.currentThread().getId() + " put竞争失败,挂起");
            this.wait();
            System.out.println(Thread.currentThread().getId() + " put被唤醒,二次激活");
        }
        doPut(v);
        this.notifyAll();//唤醒所有在this对象上挂起的线程
    }

    public synchronized V take() throws InterruptedException {
        while (isEmpty()) {
            System.out.println(Thread.currentThread().getId() + " get竞争失败,挂起");
            this.wait();//线程挂起,放开锁synchronized中this对象。
            System.out.println(Thread.currentThread().getId() + " get被唤醒,二次激活");
        }
        V v = doTake();
        this.notifyAll();//唤醒所有在this对象上挂起的线程
        return v;
    }

    public static void main(String... args) throws InterruptedException {

        BoundedBuffer<Integer> integerBoundedBuffer = new BoundedBuffer<Integer>(12);
//        new Thread(new Consummer(integerBoundedBuffer)).start();
//        TimeUnit.SECONDS.sleep(10);
        new Thread(new Producer(integerBoundedBuffer)).start();
        //通过下面可以看到  调用wait挂起线程时会释放锁.
//        new Thread(new Producer(integerBoundedBuffer)).start();



    }

    private static class Consummer implements Runnable {

        private final BoundedBuffer bf;

        public Consummer(BoundedBuffer bf) {
            this.bf = bf;
        }

        public void run() {
            try {
                while (true) {
                    bf.take();
                    System.out.println("get");
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }


    private static class Producer implements Runnable {
        private final BoundedBuffer bs;

        protected Producer(BoundedBuffer bs) {
            this.bs = bs;
        }

        public void run() {
            try {
                while (true) {
                    bs.put(123);
                    System.out.println("put");
                }

            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

}

 

posted @ 2018-03-21 16:10  张秀杰  阅读(1000)  评论(0编辑  收藏  举报