欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java阻塞队列 - LinkedBlockingQueue

程序员文章站 2024-02-11 12:45:34
...

LinkedBlockingQueue是Java并发包中一种基于链表结构实现的有界阻塞队列,

  • 以下是该类的继承结构图:
    Java阻塞队列 - LinkedBlockingQueue
  • 以下是该类的结构:
    Java阻塞队列 - LinkedBlockingQueue

LinkedBlockingQueue类:
实现了2个接口:BlockingQueue、Serializable
继承了1个抽象类:AbstractQueue
拥有3个内部类:Node、Itr、LBQSpliterator
拥有3个构造方法:LinkedBlockingQueue()、LinkedBlockingQueue(int capacity)、LinkedBlockingQueue(Collection<? extends E> c)
声明了8个变量:

private final int capacity;
private final AtomicInteger count = new AtomicInteger();
transient Node<E> head;
private transient Node<E> last;
private final ReentrantLock takeLock = new ReentrantLock();
private final Condition notEmpty = takeLock.newCondition();
private final ReentrantLock putLock = new ReentrantLock();
private final Condition notFull = putLock.newCondition();

实现了28个方法:

  • 6个private方法
//设置队列不为空信号,添加元素操作使用
private void signalNotEmpty() 
//设置队列不满信号,移出元素操作使用
private void signalNotFull()
//元素入队操作
private void enqueue(Node<E> node)
//元素出队操作
private E dequeue()
//将队列中元素写入流文件
private void writeObject(java.io.ObjectOutputStream s)
//读流文件元素到队列中
private void readObject(java.io.ObjectInputStream s)
  • 3个default方法
//进队与出队全锁
void fullyLock()
//进队与出队全解锁
void fullyUnlock()
//remove队列某元素时连接删除元素两端的队列
void unlink(Node<E> p, Node<E> trail)
  • 19个public方法
//返回队列中元素个数
public int size()
//返回队列中剩余空间
public int remainingCapacity()
//队列中添加元素,队列满时,阻塞队列,直到队列有空间时唤醒线程
public void put(E e)
//队列中添加元素,队列满时,等待timeout的时间,如果仍然是满的则返回false
public boolean offer(E e, long timeout, TimeUnit unit)
//队列中添加元素,队列满时,返回false
public boolean offer(E e)
//队列中移出元素,队列空时,阻塞队列,直到队列不为空时唤醒线程
public E take()
//队列中移出元素,队列空时,等待timeout的时间,如果仍然是空的则返回null
public E poll(long timeout, TimeUnit unit)
//队列中移出元素,队列空时,返回null
public E poll()
//返回首元素
public E peek()
//将某元素移出队列
public boolean remove(Object o)
//遍历队列查找某元素是否存在
public boolean contains(Object o)
//将队列中元素转成对象数组
public Object[] toArray()
/将队列中元素转成元素数组
public <T> T[] toArray(T[] a)
//将队列中元素按照一定格式打印输出
public String toString()
//清空队列
public void clear()
//将队列中全部元素移动到集合中
public int drainTo(Collection<? super E> c)
//将队列中指定数量的元素移动到集合中
public int drainTo(Collection<? super E> c, int maxElements)
//返回迭代队列的迭代器,便于队列的遍历
public Iterator<E> iterator()
//返回可分割迭代器,便于多线程执行
public Spliterator<E> spliterator()

以下简单介绍入队、出队方法、添加元素、移出元素方法

队尾入队、队首出队

  • 入队方法
private void enqueue(Node<E> node) {
    /** 连等式:
     * 第一步、将新元素赋值给旧队尾指针
     * 第一步、将新元素赋值给新队尾元素
     */
    last = last.next = node;
}
  • 出队方法

出对方法涉及到队首和首元素两个变量
整个过程是
将首元素指针赋值给队首
将首元素值取出
将首元素值置空

private E dequeue() {
	//队首指针赋值给临时变量h
    Node<E> h = head;
    //首元素指针赋值给临时变量first
    Node<E> first = h.next;
    //队首指针赋值给首元素(*)
    h.next = h; 
    //首元素赋值给队首
    head = first;
    //首元素值取出,放到临时变量x
    E x = first.item;
    //将首元素值置空,此时首元素已变为队首
    first.item = null;
    return x;
}
  • 添加元素

添加元素有3种方式

public void put(E e) throws InterruptedException {
	//添加元素为空,抛出空指针异常
    if (e == null) throw new NullPointerException();
    //声明临时变量c表示当前队列元素个数
    int c = -1;
    //声明元素,初始化赋元素值
    Node<E> node = new Node<E>(e);
    //声明临时变量,将添加元素锁赋值给该变量
    final ReentrantLock putLock = this.putLock;
    //声明临时变量,将元素当前个数赋值给该变量
    final AtomicInteger count = this.count;
    //入队操作前上入队锁
    putLock.lockInterruptibly();
    try {
       	//当队列元素满时,线程一直阻塞
        while (count.get() == capacity) {
            notFull.await();
        }
        //元素入队
        enqueue(node);
        //将当前队列元素个数+1操作并赋给临时变量c
        c = count.getAndIncrement();
        //如果c+1小于队列容量,表示队列未满,仍可添加元素
        if (c + 1 < capacity)
            notFull.signal();
    } finally {
    	//入队操作后解入队锁,其他线程可以获取入队锁
        putLock.unlock();
    }
    //如果
    if (c == 0)
        signalNotEmpty();
}
相关标签: 并发

上一篇: java-阻塞队列

下一篇: Java阻塞队列