详细分析Java并发集合LinkedBlockingQueue的用法

数组的长度在创建时就必须确定,如果数组长度小了,那么ArrayBlockingQueue队列很容易就被阻塞,如果数组长度大了,就容易浪费内存。而队列这个数据结构天然适合用链表这个形式,而LinkedBlockingQueue就是使用链表方式实现的阻塞队列。
一、链表实现
1.1 Node内部类

/**
 * 链表的节点,同时也是通过它来实现一个单向链表 
 */
 static class Node<E> {
   
  E item;   

 // 指向链表的下一个节点  
 Node<E> next;   

 Node(E x) {
    item = x; }
}

有一个变量e储存数据,有一个变量next指向下一个节点的引用。它可以实现最简单地单向列表。
1.2 怎样实现链表

/**
 * 它的next指向队列头,这个节点不存储数据 
 */
 transient Node<E> head;
 /** 
 * 队列尾节点 
 */
 private transient Node<E> last;

要实现链表,必须有两个变量,一个表示链表头head,一个表示链表尾last。head和last都会在LinkedBlockingQueue对象创建的时候被初始化。

last = head = new Node<E>(null);

注意这里用了一个小技巧,链表头head节点并没有存放数据,它指向的下一个节点,才真正存储了链表中第一个数据。而链表尾last的确储存了链表最后一个数据。
1.3 插入和删除节点

/**
  * 向队列尾插入节点  
  */ 
  private void enqueue(Node<E> node) {
     
   // assert putLock.isHeldByCurrentThread(); // 当前线程肯定获取了putLock锁   
   // 将原队列尾节点的next引用指向新节点node,然后再将node节点设置成队列尾节点last   
   // 这样就实现了向队列尾插入节点   
   last = last.next = node; 
}

在链表尾插入节点很简单,将原队列尾last的下一个节点next指向新节点node,再将新节点node赋值给队列尾last节点。这样就实现了插入一个新节点。

// 移除队列头节点,并返回被删除的节点数据
private E dequeue() {
    
 // assert takeLock.isHeldByCurrentThread(); // 当前线程肯定获取了takeLock锁
 // assert head.item == null;  

 Node<E> h = head;  
 // first节点中才存储了队列中第一个元素的数据  
 Node<E> first = h.next;  
 h.next = h; // help GC  
 // 设置新的head值,相当于删除了first节点。因为head节点本身不储存数据  
 head = first;  
 // 队列头的数据  
 E x = first.item;  
 // 移除原先的数据  
 first.item = null;  
 return x;
}

要注意head并不是链表头,它的next才是指向链表头,所以删除链表头也很简单,就是将head.next赋值给head,然后返回原先head.next节点的数据。
删除的时候,就要注意链表为空的情况。head.next的值使用enqueue方法添加的。当head.nextlast的时候,表示已经删除到最后一个元素了,当head.nextnull的时候,就不能删除了,因为链表已经为空了。这里没有做判断,是因为在调用dequeue方法的地方已经做过判断了。
二、同步锁ReentrantLock和条件Condition
因为阻塞队列在队列为空和队列已满的情况下,都必须阻塞等待,那么就天然需要两个条件。而为了保证多线程并发安全,又需要一个同步锁。这个在ArrayBlockingQueue中已经说过了。这里我们来说说LinkedBlockingQueue不一样的地方。

/** 独占锁,用于处理插入队列操作的并发问题,即put与offer操作 */
private final ReentrantLock putLock = new ReentrantLock
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值