深入浅出 java concurrency (25): 并发容器 part 10 双向并发阻塞队列 blockingdeque -凯发k8网页登录

关注后端架构、中间件、分布式和并发编程

   :: 凯发k8网页登录首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  111 随笔 :: 10 文章 :: 2680 评论 :: 0 trackbacks

这个小节介绍queue的最后一个工具,也是最强大的一个工具。从名称上就可以看到此工具的特点:双向并发阻塞队列。所谓双向是指可以从队列的头和尾同时操作,并发只是线程安全的实现,阻塞允许在入队出队不满足条件时挂起线程,这里说的队列是指支持fifo/filo实现的链表。

 

首先看下linkedblockingdeque的数据结构。通常情况下从数据结构上就能看出这种实现的优缺点,这样就知道如何更好的使用工具了。

从数据结构和功能需求上可以得到以下结论:

  1. 要想支持阻塞功能,队列的容量一定是固定的,否则无法在入队的时候挂起线程。也就是capacity是final类型的。
  2. 既然是双向链表,每一个结点就需要前后两个引用,这样才能将所有元素串联起来,支持双向遍历。也即需要prev/next两个引用。
  3. 双向链表需要头尾同时操作,所以需要first/last两个节点,当然可以参考linkedlist那样采用一个节点的双向来完成,那样实现起来就稍微麻烦点。
  4. 既然要支持阻塞功能,就需要锁和条件变量来挂起线程。这里使用一个锁两个条件变量来完成此功能。

 

有了上面的结论再来研究linkedblockingdeque的优缺点。

优点当然是功能足够强大,同时由于采用一个独占锁,因此实现起来也比较简单。所有对队列的操作都加锁就可以完成。同时独占锁也能够很好的支持双向阻塞的特性。

凡事有利必有弊。缺点就是由于独占锁,所以不能同时进行两个操作,这样性能上就大打折扣。从性能的角度讲linkedblockingdeque要比linkedblockingqueue要低很多,比cocurrentlinkedqueue就低更多了,这在高并发情况下就比较明显了。

前面分析足够多的queue实现后,linkedblockingdeque的原理和实现就不值得一提了,无非是在独占锁下对一个链表的普通操作。

有趣的是此类支持序列化,但是node并不支持序列化,因此fist/last就不能序列化,那么如何完成序列化/反序列化过程呢?

清单1 linkedblockingdeque的序列化、反序列化

private void writeobject(java.io.objectoutputstream s)
    throws java.io.ioexception {
    lock.lock();
    try {
        // write out capacity and any hidden stuff
        s.defaultwriteobject();
        // write out all elements in the proper order.
        for (node p = first; p != null; p = p.next)
            s.writeobject(p.item);
        // use trailing null as sentinel
        s.writeobject(null);
    } finally {
        lock.unlock();
    }
}

private void readobject(java.io.objectinputstream s)
    throws java.io.ioexception, classnotfoundexception {
    s.defaultreadobject();
    count = 0;
    first = null;
    last = null;
    // read in all elements and place in queue
    for (;;) {
        e item = (e)s.readobject();
        if (item == null)
            break;
        add(item);
    }
}

 

清单1 描述的是linkedblockingdeque序列化/反序列化的过程。序列化时将真正的元素写入输出流,最后还写入了一个null。读取的时候将所有对象列表读出来,如果读取到一个null就表示结束。这就是为什么写入的时候写入一个null的原因,因为没有将count写入流,所以就靠null来表示结束,省一个整数空间。

 



©2009-2014 imxylz
|求贤若渴
posted on 2010-08-18 16:01 imxylz 阅读(9601) 评论(5)     所属分类: java concurrency
# re: 深入浅出 java concurrency (25): 并发容器 part 10 双向并发阻塞队列 blockingdeque[未登录] 2010-08-19 16:25
楼主走神了,这么久来更新一次。哈哈  回复  
  

# re: 深入浅出 java concurrency (25): 并发容器 part 10 双向并发阻塞队列 blockingdeque[未登录] 2010-11-16 16:38
楼主怎么不继续拉,想看啊~  回复  
  

# re: 深入浅出 java concurrency (25): 并发容器 part 10 双向并发阻塞队列 blockingdeque 2011-02-15 10:46
最底部导航有些小问题,哈哈。  回复  
  

# re: 深入浅出 java concurrency (25): 并发容器 part 10 双向并发阻塞队列 blockingdeque 2011-02-15 10:51 xylz
@hixiaomin
你真仔细,赞!  回复  
  

# re: 深入浅出 java concurrency (25): 并发容器 part 10 双向并发阻塞队列 blockingdeque[未登录] 2016-04-22 15:19
mark,今天看到这里啦,满满的成就感。。。。。嘿嘿  回复  
  


©2009-2014
网站地图