美文网首页
并发集合9-LinkedTransferQueue

并发集合9-LinkedTransferQueue

作者: zhanglbjames | 来源:发表于2017-06-26 17:25 被阅读0次

    前言

    1. LinkedTransferQueue是JDK1.7才添加的阻塞队列,基于链表实现的FIFO无界阻塞队列,是ConcurrentLinkedQueue(循环CAS+volatile 实现的wait-free并发算法)SynchronousQueue(公平模式下转交元素)LinkedBlockingQueue(阻塞Queue的基本方法)的超集。而且LinkedTransferQueue更好用,因为它不仅仅综合了这几个类的功能,同时也提供了更高效的实现

    2. BlockingQueue接口,它是指这样的一个队列:当生产者向队列添加元素但队列已满时,生产者会被阻塞;当消费者从队列移除元素但队列为空时,消费者会被阻塞

    3. LinkedTransferQueue采用的一种预占模式。意思就是消费者线程取元素时,如果队列为空,那就生成一个节点(节点元素为null)入队,然后消费者线程被等待在这个节点上,后面生产者线程入队时发现有一个元素为null的节点,生产者线程就不入队了,直接就将元素填充到该节点唤醒该节点等待的线程,被唤醒的消费者线程取走元素,从调用的方法返回。即找到匹配的节点不入队,找不到根据how参数入队。

    TransferQueue接口


    TransferQueue继承自BlockingQueue接口

    LinkedTransferQueue定义


    实现了TransferQueue接口

    LinkedTransferQueue链表节点Node



    将没有匹配的数据节点进行匹配,匹配成功后设置item为null,队列中占位,然后阻塞等待在此节点上的消费者,等待被唤醒被唤醒则返回true。


    匹配前后节点item的变化,其中node1为数据节点,node2是消费者请求的占位节点

    1. 数据节点,则匹配前item不为null且不为自身,匹配后设置为null。
    2. 占位请求节点,匹配前item为null,匹配后自连接。

    LinkedTransferQueue重要字段


    head和tail节点初始化时都为null


    构造器


    LinkedTransferQueue是无界队列,并没有指定容量的构造器

    xfer核心方法

    实现所有队列的出队入队方法的通用方法

    how 参数



    xfer方法



    简单说一下xfer方法的流程

    1. 寻找和操作匹配的节点
    • 从head开始向后遍历寻找未被匹配的节点,找到一个未被匹配的节点再判断操作和节点类型是否匹配(put和占位请求节点匹配,take和数据节点匹配),如果不匹配则跳出内循环再从head开始寻找未匹配节点(重复),否则通过CAS设置匹配节点的item为e,设置成功后再CAS设置新的head节点为匹配节点的后继节点,向后推进head,将原来的head节点自连接,等待被GC,然后唤醒阻塞在这个节点上的线程,并返回匹配节点的item元素元素没有入队,而是直接从生产者转交给消费者。
    • 上面可分两个步骤:找到未被匹配的节点,然后对节点的类型进行判断和设置head
    • put和take的不同:put本身带有data(e != null),put找到匹配的节点,如果节点类型也满足(not isData),则将e设置为p的item元素,并向后推进head,然后唤醒等待的线程,并返回匹配节点原来的item(null);take本身不带data(e == null),take找到匹配的节点,如果节点类型也满足( isData),则将e设置为p的item元素(item变为null),并向后推进head,然后唤醒等待的线程,并返回匹配节点原来的item(not null)。
    1. 如果遍历整个队列都没有匹配的节点,则执行相对应的how操作处理

    注意如果isData为false,则是将一个占位请求节点插入队列尾部。

    • NOW:立即返回,也不会插入节点
    • SYNC:插入一个item为e(isData = haveData)到队列的尾部,然后自旋或阻塞当前线程直到节点被匹配或者取消。
    • ASYNC:插入一个item为e(isData = haveData)到队列的尾部,不阻塞直接返回。
    • TIMED:插入一个item为e(isData = haveData)到队列的尾部,然后自旋或阻塞当前线程直到节点被匹配或者取消或者超时
    1. 阻塞或者自旋

    插入的占位节点自旋超过一个阀值时将阻塞线程,当频繁写操作时避免过度自旋消耗CPU

    ASYNC操作(put、offer、add)

    how 参数为ASYNC,即找不到匹配节点,则入队不等待直接返回


    NOW操作(poll、tryTransfer)

    how 参数为NOW,即找不到匹配节点,则将构建新节点入队并立即返回


    SYNC操作(transfer、take)

    how 参数为SYNC,即找不到匹配节点,则将构建新节点入队并阻塞线程直到节点被匹配或被取消


    TIMED操作(poll、tryTransfer)

    how 参数为TIMED,即找不到匹配节点,则将构建新节点入队并阻塞线程直到节点被匹配或被取消或者超时


    用途与注意事项

    1. 使用LinkedTransferQueue来代替SynchronousQueue也会使得ThreadPoolExecutor得到相应的性能提升

    2. 尽量避免使用how == SYNC的操作,因为LinkedTransferQueue是无界队列当大量线程都阻塞,则会占用大量的线程资源

    相关文章

      网友评论

          本文标题:并发集合9-LinkedTransferQueue

          本文链接:https://www.haomeiwen.com/subject/lkkfqxtx.html