java blockingqueue原理是什么?原理详解

KLQ 2020-06-24 16:52:24 java常见问答 8728

你知道java当中blockingqueue原理吗?很多人表示对于blockingqueue的原理不大清楚,那么接下来就一起通过下面的文章内容来了解一下吧。

blockingqueue也就是我们经常说的阻塞队列,根据blockingqueue的基本原理,可以实现Web当中的长连接聊天功能,但是,比较常用的还是用在实现生产者和消费者模式。

在java当中,blockingqueue是一个接口,实现类有ArrayBlockingQueue、DelayQueue、 LinkedBlockingDeque、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue等等。

blockingqueue的内部有一个ReentrantLock,它生成了2个Condition,在ArrayBlockingQueue的属性声明当中,能够看见。

/** Main lock guarding all access */
final ReentrantLock lock;
/** Condition for waiting takes */
private final Condition notEmpty;
/** Condition for waiting puts */
private final Condition notFull;
...
public ArrayBlockingQueue(int capacity, boolean fair)
{
    if (capacity <= 0)
        throw new IllegalArgumentException();
    this.items = new Object[capacity];
    lock = new ReentrantLock(fair);
    notEmpty = lock.newCondition();
    notFull = lock.newCondition();
}

假如,能够将notEmpty、notFull、put线程、take线程拟人的话,那么,put和take操作很有可能是下面这样的:

put(e)

blockingqueue原理

take()

blockingqueue原理

在这当中,ArrayBlockingQueue.put(E e)源码如下:

/**
 * Inserts the specified element at the tail of this queue, waiting
 * for space to become available if the queue is full.
 *
 * @throws InterruptedException {@inheritDoc}
 * @throws NullPointerException {@inheritDoc}
 */
public void put(E e) throws InterruptedException
{
    checkNotNull(e);
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try
    {
        while (count == items.length)
            notFull.await(); // 如果队列已满,则等待
        insert(e);
    }
    finally
    {
        lock.unlock();
    }
}
/**
 * Inserts element at current put position, advances, and signals.
 * Call only when holding lock.
 */
private void insert(E x)
{
    items[putIndex] = x;
    putIndex = inc(putIndex);
    ++count;
    notEmpty.signal(); // 有新的元素被插入,通知等待中的取走元素线程
}

ArrayBlockingQueue.take()源码如下:

public E take() throws InterruptedException
{
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try
    {
        while (count == 0)
            notEmpty.await(); // 如果队列为空,则等待
        return extract();
    }
    finally
    {
        lock.unlock();
    }
}
/**
 * Extracts element at current take position, advances, and signals.
 * Call only when holding lock.
 */
private E extract()
{
    final Object[] items = this.items;
    E x = this. < E > cast(items[takeIndex]);
    items[takeIndex] = null;
    takeIndex = inc(takeIndex);
    --count;
    notFull.signal(); // 有新的元素被取走,通知等待中的插入元素线程
    return x;
}

这里可以知道,put(E)和take()是同步的。

在put操作当中,队列满了,会阻塞put操作,直到队列中有空闲的位置,在take操作当中,队列是空的时候,会阻塞take操作,一直到队列当中有新的元素。

这里是话使用2个Condition,这样是能够调用signal()的时候,会唤醒相同的put或者是take操作。

对于blockingqueue的基本原理就给你介绍到这里了,你都了解了吗?更多blockingqueue常见问题,可以继续关注奇Q工具网来进行了解哦。

推荐阅读:

blockingqueue是什么?是什么意思?

java semaphore是什么?semaphore什么意思?

nosql的特点是什么?有什么特点?