notify()和wait()实现BlockingQueue

BlockingQueue,队列对于很多人来说非常陌生.queue就是队列,BlockingQueue支持阻塞的机制,阻塞的放入数据和阻塞的得到数据.我们直接实现一个LinkedBlockingQueue 有序有界阻塞队列,上代码.再分析~~

public class Myqueue {

    private final LinkedList list = new LinkedList<>();

    private final AtomicInteger count = new AtomicInteger(0);

    private final int minSize = 0;

    private final int maxSize;

    public Myqueue(int size) {
        this.maxSize = size;
    }
    
    private final Object object = new Object();

    public String take() {
        String string = null;
        synchronized (object) {
            while (count.get() == minSize) {
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            string = list.removeFirst();

            count.decrementAndGet();

            object.notify();

            return string;
        }
    }

    public void put(String str) {
        synchronized (object) {
            while (count.get() == maxSize) {
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            list.add(str);
            
            count.incrementAndGet();
            
            object.notify();
            
            System.out.println("新加入的元素为:" + str);
        }

    }

    public static void main(String[] args) {

        final Myqueue myqueue = new Myqueue(5);
        myqueue.put("a");
        myqueue.put("b");
        myqueue.put("c");
        myqueue.put("d");
        myqueue.put("e");

        Thread thread1 = new Thread(new Runnable() {
            public void run() {
                myqueue.put("f");
                myqueue.put("g");
            }
        });
        thread1.start();

        Thread thread2 = new Thread(new Runnable() {
            public void run() {
                String string1 = myqueue.take();
                System.out.println("获得的元素为-->" + string1);
                String string2 = myqueue.take();
                System.out.println("获得的元素为-->" + string2);
            }
        });

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread2.start();
    }
}

不要被代码给吓到,其实一点一点分析一点都不难.首先我们直接看定义的东西.

表示的是定义一个有序的数组.↓↓↓↓↓↓↓

 private final LinkedList list = new LinkedList<>();

利用AtomicInteger来实现原子性的递增递减操作.↓↓↓↓↓↓↓

 private final AtomicInteger count = new AtomicInteger(0);

数据能接受的最小长度.↓↓↓↓↓↓↓

private final int minSize = 0;

数组能接受的最大长度,通过构造方法传入,毕竟要有界啊~↓↓↓↓↓↓↓

private final int maxSize;

利用 synchronized 的对象锁.↓↓↓↓↓↓↓

private final Object object = new Object();

定义的东西看完了,先不看代码,上分析图(文字版)~

(put)----> (0,0,0,0,0)----->(take)

看上面的小图.

put:如果容器中没有存到5个元素(也就是容器最大值),那么我正常put操作,如果我的容器已经存在5个元素,那么想再往里添加元素也就是put操作,肯定是添加不进去的,所以必须得阻塞着,等到容器中的元素被拿走.

take:如果容器中存在元素,那么我就take操作,取出元素.如果容器中的元素已经没有了,那么take就得阻塞着,等待着容器中有数据,也就是put操作.

上面的情况真的结束了吗?考虑一种极端的.容器中如果已经满了,想put操作肯定是不可以的,但是想put肯定要通知(notify())take.告诉take:啊你可以拿元素了....是吧 反之,如果容器中没有数据了,take也必须告诉(notify())put:哦你也可以放元素了

然后我们再看上面的代码,结合场景,自悟~~~~~

打印结果放上~

新加入的元素为:a
新加入的元素为:b
新加入的元素为:c
新加入的元素为:d
新加入的元素为:e
获得的元素为-->a
新加入的元素为:f
获得的元素为-->b
新加入的元素为:g

有啥不懂的请加qq727865942,微信号 cto_zej,觉得是干货请打赏~~~~~~~~~~

你可能感兴趣的:(notify()和wait()实现BlockingQueue)