队列总结(八)LinkedTransferQueue

【Java多线程】JUC之并发容器—深入剖析并发队列LinkedTransferQueue(八) - **LinkedTransferQueue**: 一个由`链表`结构组成的`无界阻塞队列`,相对于其它队列该类实现了**TransferQueue接口**,多了`transfer()和tryTransfer()`方法。 - **若当前存在一个正在等待transfer元素的消费者线程,就直接将元素 “交给” 等待者;否则会put当前元素到队尾,并进入阻塞状态,等待消费者线程transfer该元素。** 阅读详情

LinkedTransferQueue

无界阻塞队列LinkedTransferQueue,此队列也是基于链表实现,对于所有给定的元素都是先入先出的。LinkedTransferQueue可以算是 LinkedBolckingQueue 和 SynchronousQueue 的合体。SynchronousQueue 内部无法存储元素,当要添加元素的时候,需要阻塞。LinkedBolckingQueue 则内部使用了大量的锁,性能有所下降。

public class LinkedTransferQueue<E> extends AbstractQueue<E>
    implements TransferQueue<E>, java.io.Serializable {

TransferQueue接口

public interface TransferQueue<E> extends BlockingQueue<E> {
    // 如果可能,立即将元素转移给等待的消费者。 
    // 更确切地说,如果存在消费者已经等待接收它(在 take 或 timed poll(long,TimeUnit)poll)中,则立即传送指定的元素,否则返回 false。
    boolean tryTransfer(E e);

    // 将元素转移给消费者,如果需要的话等待。 
    // 更准确地说,如果存在一个消费者已经等待接收它(在 take 或timed poll(long,TimeUnit)poll)中,则立即传送指定的元素,否则等待直到元素由消费者接收。
    void transfer(E e) throws InterruptedException;

    // 上面方法的基础上设置超时时间
    boolean tryTransfer(E e, long timeout, TimeUnit unit) throws InterruptedException;

    // 如果至少有一位消费者在等待,则返回 true
    boolean hasWaitingConsumer();

    // 返回等待消费者人数的估计值
    int getWaitingConsumerCount();
}

TransferQueue是JDK7才定义的一个接口,继承BlockingQueue 。通常阻塞队里,生产者放入元素,消费者使用元素,只会考虑当前队列的容量,生产者生产时不需要考虑是否有消费者消费其产品。TransferQueue定义了transfer方法,阻塞生产直至等待消费者调用take或poll接收元素。

xfer方法

在LinkedTransferQueue中,所有添加元素的方法,都是通过 xfer方法来实现的。

  private E xfer(E e, boolean haveData, int how, long nanos) {
  		// 不允许空元素
        if (haveData && (e == null))
            throw new NullPointerException();
        Node s = null;                        // the node to append, if needed

        retry:
        for (;;) {                            // restart on append race

            for (Node h = head, p = h; p != null;) { // find & match first node
                boolean isData = p.isData;
                Object item = p.item;
                if (item != p && (item != null) == isData) { // unmatched
                    if (isData == haveData)   // can't match
                        break;
                    if (p.casItem(item, e)) { // match
                        for (Node q = p; q != h;) {
                            Node n = q.next;  // update by 2 unless singleton
                            if (head == h && casHead(h, n == null ? q : n)) {
                                h.forgetNext();
                                break;
                            }                 // advance and retry
                            if ((h = head)   == null ||
                                (q = h.next) == null || !q.isMatched())
                                break;        // unless slack < 2
                        }
                        LockSupport.unpark(p.waiter);
                        return LinkedTransferQueue.<E>cast(item);
                    }
                }
                Node n = p.next;
                p = (p != n) ? n : (h = head); // Use head if p offlist
            }

            if (how != NOW) {                 // No matches available
                if (s == null)
                    s = new Node(e, haveData);
                Node pred = tryAppend(s, haveData);
                if (pred == null)
                    continue retry;           // lost race vs opposite mode
                if (how != ASYNC)      // 阻塞发生在awaitMatch中
                    return awaitMatch(s, pred, e, (how == TIMED), nanos);
            }
            return e; // not waiting
        }
    }
  /*
   * Possible values for "how" argument in xfer method.
   */
  private static final int NOW   = 0; // for untimed poll, tryTransfer
  private static final int ASYNC = 1; // for offer, put, add
  private static final int SYNC  = 2; // for transfer, take
  private static final int TIMED = 3; // for timed poll, tryTransfer

	// xfer方法中的部分代码
     if (how != NOW) {                 // No matches available
         if (s == null)
             s = new Node(e, haveData);
         Node pred = tryAppend(s, haveData);
         if (pred == null)
             continue retry;           // lost race vs opposite mode
         if (how != ASYNC)  // 阻塞发生在这里
             return awaitMatch(s, pred, e, (how == TIMED), nanos);
     }
     return e; // not waiting

其中put,offer,add方法符合接口BlockingQueue的规范,参数how都是ASYNC,表示异步,指的是生产者与消费者是异步,生产者不需要等待消费者,只需要考虑队列容量。又由于队列是无界的,所以都不会阻塞。

  public void put(E e) {
        xfer(e, true, ASYNC, 0);
    }

    public boolean offer(E e, long timeout, TimeUnit unit) {
        xfer(e, true, ASYNC, 0);
        return true;
    }

    public boolean offer(E e) {
        xfer(e, true, ASYNC, 0);
        return true;
    }
    
    public boolean add(E e) {
        xfer(e, true, ASYNC, 0);
        return true;
    }

不指定阻塞时间的transfer方法以及take方法,参数how为SYNC,表示同步,take方法语义符合接口BlockingQueue的规范,一直阻塞直至获取到元素,transfer方法表示生产者必须在有消费者等待消费的情况下才可以进行生产,否则会一直阻塞。

    public void transfer(E e) throws InterruptedException {
        if (xfer(e, true, SYNC, 0) != null) {
            Thread.interrupted(); // failure possible only due to interrupt
            throw new InterruptedException();
        }
    }

    public E take() throws InterruptedException {
        E e = xfer(null, false, SYNC, 0);
        if (e != null)
            return e;
        Thread.interrupted();
        throw new InterruptedException();
    }

不指定时间的tryTransfer方法以及poll方法,参数how为NOW,tryTransfer尝试插入元素,假如此时无消费者在等待,直接返回false,插入失败,不会阻塞。

   public E poll() {
       return xfer(null, false, NOW, 0);
   }

	public boolean tryTransfer(E e) {
	    return xfer(e, true, NOW, 0) == null;
	}

指定时间的tryTransfer方法以及poll方法,参数how为TIMED,若成功提前返回,若失败,最多阻塞指定时间。

    public E poll(long timeout, TimeUnit unit) throws InterruptedException {
        E e = xfer(null, false, TIMED, unit.toNanos(timeout));
        if (e != null || !Thread.interrupted())
            return e;
        throw new InterruptedException();
    }
    
   public boolean tryTransfer(E e, long timeout, TimeUnit unit)
       throws InterruptedException {
       if (xfer(e, true, TIMED, unit.toNanos(timeout)) == null)
           return true;
       if (!Thread.interrupted())
           return false;
       throw new InterruptedException();
   }

数据结构

LinkedTransferQueue的数据结构采用的是双重队列Dual Queues,此队列的节点为Node

 static final class Node {
        final boolean isData;   // false if this is a request node
        volatile Object item;   // initially non-null if isData; CASed to match
        volatile Node next;
        volatile Thread waiter; // null until waiting
        ...
}

队列中的节点分为两种类型,每个节点只对应一种类型的操作,要么是put类型(isData为true),要么是take类型(isData为false)

在dual队列中,节点需要自动维护匹配状态。所以这里需要一些必要的变量:对于数据模式,匹配需要将一个item字段通过CAS从非null的数据转成null,反之对于请求模式,需要从null变成data。一旦一个节点匹配了,其状态将不再改变。

当一个线程试图添加一个数据节点,正好遇到一个请求数据的结点,会立刻匹配并移除这两个数据节点,反之亦然。
在这里插入图片描述
关于节点匹配及头结点更新的逻辑,有些复杂,暂时不深入,贴上相关参考文章
https://www.cnblogs.com/lighten/p/7505355.html

对比SynchronousQueue

相比较 SynchronousQueue 多了一个可以存储的队列,相比较 LinkedBlockingQueue 多了直接传递元素,少了用锁来同步。性能更高,用处更大。

LinkedTransferQueue是 SynchronousQueue 和 LinkedBlockingQueue 的合体,性能比 LinkedBlockingQueue 更高(没有锁操作),比 SynchronousQueue能存储更多的元素。

当 put 时,如果有等待的线程,就直接将元素 “交给” 等待者, 否则直接进入队列。

put和 transfer 方法的区别是,put 是立即返回的, transfer 是阻塞等待消费者拿到数据才返回。transfer方法和 SynchronousQueue的 put 方法类似。

告别版本冲突!在Ubuntu 20.04上优雅实现ROS Noetic与ROS2 Foxy双环境切换 本文详细介绍了在Ubuntu 20.04系统上实现ROS Noetic(ROS1)与ROS2 Foxy双环境共存与切换的完整方案。通过智能脚本设计和工作空间隔离,解决了版本冲突问题,帮助开发者高效管理不同ROS版本项目。特别适合需要同时开发ROS1和ROS2应用的机器人开发者。 阅读详情

相关推荐

GEE开发之Landsat8计算MNDWI和数据分析

上一篇博客介绍了landsat8计算NDWI以及数据的获取,这次介绍MNDWI(改进的归一化差异水体指数)。

等待着冬天的风的博客 8440

LinkedTransferQueue

LinkedTransferQueue是一个由链表结构组成的无界阻塞TransferQueue队列。相对于其他阻塞队列,LinkedTransferQueue多了tryTransfer和transfer方法。可以算是 LinkedBolckingQueue 和 SynchronousQueue 和合体。LinkedTransferQueue是一种无界阻塞队列,底层基于单链表实现,其内部节点分为数据结点、请求结点;基于CAS无锁算法实现 基本原理 LinkedTransferQueue 消费者线程获取取数据时

weixin_49561445的博客 3838

JW01二氧化碳传感器实战:5分钟搞定Arduino环境监测系统(附完整代码)

本文详细介绍了如何使用JW01二氧化碳传感器与Arduino快速搭建环境监测系统。通过简单的硬件连接和完整的代码示例,读者可以在5分钟内实现CO2浓度实时监测,并了解数据解析、常见问题解决及进阶应用扩展。JW01传感器的高精度和易用性使其成为创客和嵌入式开发者的理想选择。

kite3的博客 383

深入探究Java中的TransferQueue:机制、特性与应用场景

TransferQueue是Java并发包中的一个强大工具,专为需要精确的数据传递场景而设计。它实现了BlockingQueue接口,但提供了更为独特的transfer和tryTransfer方法,允许生产者和消费者之间以同步的方式进行数据的直接传递。当生产者生成数据项时,它可以等待直到有消费者准备好接收;同样地,当消费者需要数据时,它可以等待直到有生产者提供。这种机制确保了数据在传递过程中的一致性和准确性,是构建高性能、低延迟并发系统的关键组件之一

码到三十五 1994

OpenCV形状检测

开始定义我们的ShapeDetector类。我们将跳过这里的init构造函数,因为不需要初始化任何东西。#导入必要的包importcv2classShapeDetector#初始化形状名称并近似轮廓shape="unidentified"peri=cv2.arcLength(c,True)approx=cv2.approxPolyDP(c,0.04*peri,True)我们的检测方法,它只需要一个参数c,即我们试图识别的形状的轮廓。...

weixin_43229348的博客 9424

泛微E9集成登录实战:5分钟搞定第三方系统单点登录配置(附避坑指南)

本文详细解析了泛微E9集成登录的实战配置流程与核心原理。通过理解其基于信任代理的身份传递机制,文章指导用户如何在5-10分钟内完成第三方系统的单点登录对接,涵盖基础配置、核心参数设置、高级表达式应用,并提供了编码问题、账号不一致等常见避坑指南,助力企业快速构建统一身份认证门户。

weixin_29185493的博客 296

Java并发基础:LinkedTransferQueue全面解析!

LinkedTransferQueue类实现了高效的线程间数据传递,支持等待匹配的生产者-消费者模式,基于链表的无界设计使其在高并发场景下表现卓越,且无需担心队列溢出,丰富的方法和良好的可扩展性满足了各种复杂应用场景的需求。

科技互联网领域深度探索者,乐于分享与写作。 1556

化学科学催化反应产率预测之Transformer建模SMILES(Datawhale AI 夏令营)

循环神经网络:由于所有的前文信息都蕴含在一个隐向量中,随着序列长度的增加,早期的上下文信息会逐渐被遗忘。卷积神经网络:受限的上下文窗口在建模长文本时存在天然不足。需要多层卷积操作才能处理长文本。在本篇文章中,我们学习了Transformer的基本架构及其在化学反应产率预测中的应用。通过利用Transformer的Encoder部分对SMILES进行建模,我们能够更有效地捕捉序列数据的特征,从而提高模型的预测性能。

不想宅的冷同学 1096

并发容器学习—LinkedTransferQueue

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33711647的博客 247

24、无人机能耗模型与上下文质量管理的研究

本文系统介绍了无人机能耗模型与上下文质量管理的研究进展。详细阐述了Dorling、Stolaroff、Kirchstein和Tseng等经典能耗模型的原理及特点,并基于LSTM架构构建了数据驱动的能耗预测模型,实验表明其预测精度显著优于传统模型。此外,还探讨了物联网环境中的上下文质量管理问题,引入了conQeng框架,以提升上下文选择、测量和验证的效率与可靠性。研究为无人机能耗优化和物联网上下文管理提供了理论支持和技术方案。

palm99的专栏 345

【AI工具】免费获取各类AI大模型APIKEY的使用教程,以硅基流动+Deepseek为例

【AI工具】免费获取各类AI大模型APIKEY的使用教程,以硅基流动+Deepseek为例

funfan的博客 4269

【死磕Java并发】-----J.U.C之阻塞队列:LinkedTransferQueue

原文出处http://cmsblogs.com/ 『chenssy』 前面提到的各种BlockingQueue对读或者写都是锁上整个队列,在并发量大的时候,各种锁是比较耗资源和耗时间的,而前面的SynchronousQueue虽然不会锁住整个队列,但它是一个没有容量的“队列”,那么有没有这样一种队列,它即可以像其他的BlockingQueue一样有容量又可以像SynchronousQueue一样不会

chenssy 的技术博客 4859

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Java并发编程之LinkedTransferQueue阻塞队列详解

简介LinkedTransferQueue是一个由链表结构组成的无界阻塞TransferQueue队列。相对于其他阻塞队列,LinkedTransferQueue多了tryTransfer和transfer方法。

Stay Hungry, Stay Foolish 1万+

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

LinkedTransferQueue是什么

LinkedTransferQueue是什么

weixin_45428910的博客 1010

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

【并发编程系列10】阻塞队列之SynchronousQueue,LinkedTransferQueue原理分析

LinkedTransferQueue,SynchronousQueue原理分析前言LinkedTransferQueueSynchronousQueue 前言 前面我们介绍了ArrayBlockingQueue,LinkedBlockingQueue,LinkedBlockingDeque,PriorityBlockingQueue,DelayQueue五种阻塞队列,今天继续介绍LinkedTransferQueue和SynchronousQueue两个阻塞队列。 LinkedTransferQueue

zwx900102的博客 1164

J.U.C 之阻塞队列:LinkedTransferQueue 详解

摘要:LinkedTransferQueue是Java并发包中的高性能无界阻塞队列,采用CAS无锁算法实现,特别适合高并发场景。其核心特性包括FIFO顺序、支持生产者等待消费者接收的转移操作,以及基于双重队列设计的直接匹配机制。通过实现TransferQueue接口,提供了tryTransfer、transfer等方法实现高效数据交换。与LinkedBlockingQueue和SynchronousQueue相比,在高竞争环境下性能更优,但作为无界队列需注意内存管理。最佳实践包括根据业务需求选择阻塞/非阻塞

油墨香^-^的博客 763

JAVA队列介绍(Queue)——LinkedTransferQueue

LinkedTransferQueue LinkedTransferQueue 链表实现的无界阻塞队列。相对于其他阻塞队列,LinkedTransferQueue多了tryTransfer和transfer方法。其使用一种预占的模式,当消费者获取元素的时候如果队列不为空则直接获取元素,如果队列为空,则生产一个null的元素,然后在这个节点上等待。 当有新的线程添加元素的时候,如果发现有null的元...

大风的博客 688

阻塞队列(五):LinkedTransferQueue

阻塞队列(五):LinkedTransferQueue 前面提到的各种BlockingQueue对读或者写都是锁上整个队列,在并发量大的时候,各种锁是比较耗资源和耗时间的,而前面的SynchronousQueue虽然不会锁住整个队列,但它是一个没有容量的“队列”,那么有没有这样一种队列,它即可以像其他的BlockingQueue一样有容量又可以像SynchronousQueue一样不会锁住整个队列...

木村的博客 468

阻塞队列的首选之队列超集LinkedTransferQueue

文章目录前言队列的语义切换线程安全的队列Hand-off(SynchronousQueue语义)无界的阻塞队列LTQ原理分析假设阻塞特性1. 来一个线程存数据2. 又来一个线程存数据3. 来一个线程取数据总结 前言 这次讨论的议题是 JDK 1.7 新增的一个阻塞队列LinkedTransferQueue,那么它与上一篇我们讨论的那3个基本的阻塞队列有什么不同呢?为什么JDK1.7的时候需要在JU...

|-| [- |_ |_ () 410

阅读 JDK 源码:传递队列 LinkedTransferQueue

LinkedTransferQueue 是一个由链表结构组成的无界阻塞 TransferQueue 队列。 接口 TransferQueue 和实现类 LinkedTransferQueue 从 Java 7 开始加入 J.U.C 之中。 文章目录1. 继承体系2. 数据结构2.1 节点定义2.2 head 和 tail 节点3. 构造函数4. 数据存取及传递4.1 xfer4.2 匹配过程图示4.3 tryAppend4.4 awaitMatch4.5 自旋次数4.6 unsplice5. 容量6. 总结

Sumkor的博客 363

【阻塞队列源码系列】 LinkedTransferQueue 源码解析

LinkedTransferQueue LinkedTransferQueue是下面三者的集合体 LinkedBlockingQueue(支持阻塞,即失败入队,但不再支持获取 Lock 的阻塞了,因为是基于 cas 的) SynchronousQueue(公平模式,实现了 Transfer 接口) ConcurrentLinkedQueue (支持非阻塞,因为传统的阻塞队列都是使用的 Lock,想要 offer 或者 poll 等操作必须先获得 lock,而非阻塞是 直接cas 一次,失败就直接返回,

菜鸡也有大佬梦 621

阻塞队列 — LinkedTransferQueue源码分析

点赞再看,养成习惯,公众号搜一搜【一角钱技术】关注更多原创技术文章。 本文 GitHub org_hejianhui/JavaStudy 已收录,有我的系列文章。 前言 LinkedTransferQueue 是一个由链表结构组成的无界阻塞传输队列,它是一个很多队列的结合体(ConcurrentLinkedQueue,LinkedBlockingQueue,SynchronousQueue),在除了有基本阻塞队列的功能(但是这个阻塞队列没有使用锁)之外;队列实现了TransferQueue接口重写了..

org_hjh的博客 429

LinkedTransferQueue 高效阻塞无界链表队列

LinkedTransferQueue 是一个高效阻塞无界链表队列。和SynchronousQueue.TransferQueue(公平模式)相比,它是可以统计长度,可以进行查询的;和LinkedBlockingQueue相比,它拥有更高的性能(使用CAS自旋);和ConcurrentLinkedQueue相比,它拥有阻塞功能。

袁江南的博客 693

Java进阶之线程安全队列LinkedTransferQueue:用法实例(一百六十五)

本篇目的:Java线程安全队列之LinkedTransferQueue:用法实例基本概念LinkedTransferQueue是Java并发包提供的无界链表队列,支持直接移交、阻塞与非阻塞插入,实现TransferQueue接口。功能提供transfer、tryTransfer、put、take、poll等方法,可立即移交或等待消费者,支持超时与公平策略。使用限制无容量限制,元素不可为null;高并发下需控制内存。性能特性。

Android系统攻城狮 958
上一篇: 队列总结(六)DelayQueue
下一篇: ThreadPoolExecutor
MrMoving
博客等级 码龄10年 54粉丝 145原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值