曾经被面试过BlockingQueue吗?

763 阅读2分钟
原文链接: mp.weixin.qq.com

面试时曾经被问过阻塞队列吗?

想必很多人面试时有被问到阻塞队列的经历。我们经常会在各种代码中见到或者用到它,最经常见到的地方就是线程池。

但是如果问起阻塞队列的原理,它是基于什么实现的,你是否说的上来呢?

陌生又熟悉的BlockingQueue

阻塞队列(BlockingQueue)其实也是队列,但是它有两个特点,· 当队列满时,往队列的put()操作会导致当前线程阻塞· 当队列空时,向队列的take()操作也会导致当前线程阻塞

BlockingQueue经常用在以下几个场景· 生产者&消费者· 线程间通信· 线程池

问题1:add()和put()有什么不同?

相信很多人都知道,add()其实并不是阻塞操作,当队列满时add()会抛出异常,而put()不会抛出异常。

问题2:阻塞队列的原理是什么?

看过上一篇文章的朋友肯定立马想到BlockingQueue是基于Condition,我们可以用很简单的代码写出阻塞队列的原理

final Lock lock = new ReentrantLock();final Condition notFull = lock.newCondition();final Condition notEmpty = lock.newCondition();final Object[] items = new Object[100];int putptr, takeptr, count;public void put(Object x) throws InterruptedException {    lock.lock();    try {        while (count == items.length) {            notFull.await();        }        items[putptr] = x;        if (++putptr == items.length)            putptr = 0;        ++count;        notEmpty.signal();    } finally {        lock.unlock();    }}public Object take() throws InterruptedException {    lock.lock();    try {        while (count == 0) {            notEmpty.await();        }        Object x = items[takeptr];        if (++takeptr == items.length)            takeptr = 0;        --count;        notFull.signal();        return x;    } finally {        lock.unlock();    }}

以put()为例说明,当队列满时,当前线程会等待notFull条件满足,若不满足则持续等待。直到有take()操作,队列的notFull条件满足,才会往队列放对象,同时让notEmpty条件满足,对应的take()操作才能正常进行。

总结

看完这篇文章,相信你已经明白阻塞队列的实现原理了吧。以下是它的主要子类· ArrayBlockingQueue· LinkedBlockingQueue· SynchronousQueue虽然它们的具体实现各不相同,但是原理都是一样基于Condition去实现的。

下次面试时被问到BlockingQueue的话就可以淡定的说啦!欢迎订阅关注!