前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >深入探究Java中的TransferQueue:机制、特性与应用场景

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

作者头像
公众号:码到三十五
修改于 2024-03-21 00:13:31
修改于 2024-03-21 00:13:31
23602
代码可运行
举报
文章被收录于专栏:JAVA核心JAVA核心
运行总次数:2
代码可运行

1️⃣概述

TransferQueueJava并发包java.util.concurrent中的一个接口,它扩展了BlockingQueue接口。与传统的BlockingQueue不同,TransferQueue提供了更精确的控制,允许生产者和消费者线程之间进行更直接的交互。它引入了两种新的操作方法:transfer(E e)tryTransfer(E e, long timeout, TimeUnit unit),这两种方法提供了在数据可用时的等待/传输语义。

2️⃣BlockingQueue vs TransferQueue

在深入了解TransferQueue之前,让我们先回顾一下BlockingQueueBlockingQueue是一个线程安全的队列,它支持在尝试检索元素但队列为空时等待,以及尝试添加元素但队列已满时等待。它是实现生产者-消费者模式的一种常见方式。

然而,在某些情况下,您可能需要更细粒度的控制,以确保当一个线程正在等待接收数据时,有一个对应的线程准备发送数据。这就是TransferQueue派上用场的地方。与BlockingQueue不同,TransferQueue的实现会尝试立即满足一个takeput操作的要求,如果不能立即满足,那么等待的线程将会被“匹配”到一个即将进入的相反操作。

3️⃣核心方法

TransferQueue接口声明了以下关键方法:

  1. E transfer(E e) - 将元素传输给消费者,如果可能的话,否则等待直到一个消费者准备接收它。
  2. boolean tryTransfer(E e, long timeout, TimeUnit unit) - 尝试将元素传输给等待的消费者,在指定的时间内等待,如果在给定的时间内无法完成传输,则返回false
  3. E tryTransfer(E e) - 尝试立即将元素传输给等待的消费者,如果不能立即传输,则返回null
  4. E getWaitingConsumer() - 返回正在等待接收元素的线程(如果存在的话),主要是为了监视和调试的目的。
  5. int getWaitingProducerCount() - 返回正在等待向此队列传输元素的线程数量。
  6. int getWaitingConsumerCount() - 返回正在等待从此队列接收元素的线程数量。

注意,并非所有TransferQueue实现都需要提供所有这些方法的完整实现。某些实现可能不支持全部的操作集,例如tryTransfer的超时版本。

4️⃣常见实现

LinkedTransferQueueTransferQueue接口的一个常用实现。它是一个基于链表的、无界的阻塞队列。与ArrayBlockingQueueLinkedBlockingQueue相比,LinkedTransferQueue的传输操作具有不同的特性。

  • 公平性:与一些其他阻塞队列不同,LinkedTransferQueue通常遵循FIFO原则,但不保证元素的顺序在多生产者和多消费者环境下绝对精确。
  • 无界LinkedTransferQueue在逻辑上是无界的,这意味着你可以放入任意多的元素,只要你的程序有足够的内存来处理它们。然而,在实践中,队列的容量受到JVM可用内存的限制。
  • 高效的传输操作LinkedTransferQueue使用一种称为"双重数据链接"的策略,使得传输操作可以在恒定的时间内完成,而与队列中元素的数量无关。

5️⃣使用场景

TransferQueue通常用于以下场景:

  • 当需要在生产者线程和消费者线程之间进行精确匹配时,以确保生产者的数据可以立即被消费者处理。
  • 当生产者需要等待消费者准备好接收数据,而不仅仅是等待空间在队列中变得可用时。
  • 当你想要利用Java并发包的强大功能来实现高级的多线程协调策略时。

6️⃣LinkedTransferQueue实现生产者-消费者场景

下面代码使用LinkedTransferQueue实现一个简单的生产者-消费者场景,其中生产者生成数据并将其传输给消费者,消费者处理这些数据。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import java.util.concurrent.*;

public class TransferQueueDemo {

    // 定义生产的数据类型
    static class DataItem {
        int id;

        public DataItem(int id) {
            this.id = id;
        }

        @Override
        public String toString() {
            return "DataItem{" + "id=" + id + '}';
        }
    }

    // 生产者任务
    static class Producer implements Runnable {
        private final TransferQueue<DataItem> queue;

        public Producer(TransferQueue<DataItem> queue) {
            this.queue = queue;
        }

        @Override
        public void run() {
            try {
                for (int i = 0; i < 10; i++) {
                    DataItem item = new DataItem(i);
                    System.out.println("生产者生产了数据: " + item);
                    // 将数据传输给消费者,如果消费者未准备好,生产者将等待
                    queue.transfer(item);
                    // 模拟生产耗时
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    // 消费者任务
    static class Consumer implements Runnable {
        private final TransferQueue<DataItem> queue;

        public Consumer(TransferQueue<DataItem> queue) {
            this.queue = queue;
        }

        @Override
        public void run() {
            try {
                while (true) {
                    // 从队列中接收数据,如果没有数据,消费者将等待
                    DataItem item = queue.take();
                    System.out.println("消费者消费了数据: " + item);
                    // 模拟消费耗时
                    Thread.sleep(1500);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    public static void main(String[] args) {
        // 创建一个LinkedTransferQueue实例
        TransferQueue<DataItem> queue = new LinkedTransferQueue<>();

        // 启动生产者线程
        Thread producerThread = new Thread(new Producer(queue));
        producerThread.start();

        // 启动消费者线程
        Thread consumerThread = new Thread(new Consumer(queue));
        consumerThread.start();
    }
}
  • 我们定义了一个名为DataItem的简单类来持有数据。Producer类实现了Runnable接口,并在其run方法中循环生成DataItem对象,并使用transfer方法将它们放入TransferQueue。如果此时没有消费者在等待接收数据,生产者线程将会阻塞。
  • Consumer类也实现了Runnable接口,并在其run方法中无限循环地从TransferQueue中取出数据项(通过take方法),然后模拟消费这些数据。如果队列为空,消费者线程将会阻塞,直到生产者放入新的数据项。
  • main方法中,我们创建了一个LinkedTransferQueue实例,并分别启动了一个生产者和一个消费者线程。这个程序将持续运行,直到被外部中断或者手动停止。

7️⃣总结

TransferQueue是一个功能强大的并发工具,它扩展了标准的阻塞队列概念,允许生产者和消费者之间进行更直接和精确的数据传输。通过使用TransferQueue,你可以构建更复杂、更高效的多线程应用程序,同时减少因资源竞争而导致的线程等待时间。在选择TransferQueue时,请考虑你的应用程序是否需要这种高级别的控制和协调,以及你选择的TransferQueue实现是否满足你的性能和功能需求。



术因分享而日新,每获新知,喜溢心扉。 诚邀关注公众号 码到三十五 ,获取更多技术资料。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-03-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
java中的Queue家族详解
java中Collection集合有三大家族List,Set和Queue。当然Map也算是一种集合类,但Map并不继承Collection接口。
程序那些事
2020/07/08
5930
java中的Queue家族详解
死磕 java集合之LinkedTransferQueue源码分析
(4)LinkedTransferQueue与SynchronousQueue有什么异同?
彤哥
2019/07/08
5860
死磕 java集合之LinkedTransferQueue源码分析
高并发之并发容器,了解多少(从入门到超神)
在上面已经提到过ConcurrentHashMap,ConcurrentHashMap相比Hashtable能够进一步提高并发性,其原理图如下:
好好学java
2018/10/18
6130
阻塞队列实现之LinkedTransferQueue源码解析
LinkedTransferQueue在JDK1.7版本诞生,是由链表组成的无界TransferQueue,相对于其他阻塞队列,多了tryTransfer和transfer方法。
烂猪皮
2023/09/04
1510
阻塞队列实现之LinkedTransferQueue源码解析
TransferQueue实例
TransferQueue(java7引入)继承了BlockingQueue(BlockingQueue又继承了Queue)并扩展了一些新方法。生产者会一直阻塞直到所添加到队列的元素被某一个消费者所消费(不仅仅是添加到队列里就完事)。
code4it
2018/09/17
1.6K0
小米大模型数据开发工程师-武汉
首先是对于大模型的理解,最经典的就是chatgpt,PI AI,claude2, Bard,这些是市面上使用体验最好的大语言模型,这也是我平日生活中工作学习必不可少的部分,从它诞生开始我就一直持续的使用,不论是官网的还是二次创作的插件。
GeekLiHua
2025/01/21
1310
小米大模型数据开发工程师-武汉
【死磕Java并发】-----J.U.C之阻塞队列:LinkedTransferQueue
原文出处http://cmsblogs.com/ 『chenssy』 前面提到的各种BlockingQueue对读或者写都是锁上整个队列,在并发量大的时候,各种锁是比较耗资源和耗时间的,而前面的SynchronousQueue虽然不会锁住整个队列,但它是一个没有容量的“队列”,那么有没有这样一种队列,它即可以像其他的BlockingQueue一样有容量又可以像SynchronousQueue一样不会锁住整个队列呢?有!答案就是LinkedTransferQueue。 LinkedTransferQueue是
用户1655470
2018/04/26
7310
【死磕Java并发】-----J.U.C之阻塞队列:LinkedTransferQueue
(76) 并发容器 - 各种队列 / 计算机程序的思维逻辑
本节,我们来探讨Java并发包中的各种队列。Java并发包提供了丰富的队列类,可以简单分为: 无锁非阻塞并发队列:ConcurrentLinkedQueue和ConcurrentLinkedDeque 普通阻塞队列:基于数组的ArrayBlockingQueue,基于链表的LinkedBlockingQueue和LinkedBlockingDeque 优先级阻塞队列:PriorityBlockingQueue 延时阻塞队列:DelayQueue 其他阻塞队列:SynchronousQueue和LinkedT
swiftma
2018/01/31
6160
干货 | 45张图庖丁解牛18种Queue,你知道几种?
在讲《21张图讲解集合的线程不安全》那一篇,我留了一个彩蛋,就是Queue(队列)还没有讲,这次我们重点来看看Java中的Queue家族,总共涉及到18种Queue。这篇恐怕是市面上最全最细 讲解Queue的。
悟空聊架构
2020/09/10
5350
Java 阻塞队列 BlockingQueue 介绍: put,add 和 offer 三个方法
在多线程编程中,经常需要使用线程安全的数据结构,用于在不同线程之间进行数据交换和通信。Java提供了一种称为阻塞队列(BlockingQueue)的数据结构,它是线程安全的队列实现,提供了一些特殊的方法来处理多线程环境下的数据交换问题。本文将介绍阻塞队列的基本概念和在Java中使用的三种常见方法:put,add和offer。
大盘鸡拌面
2023/11/02
9350
synchronousqueue场景_SynchronousQueue原理解析
SynchronousQueue 也是一个队列来的,但它的特别之处在于它内部没有容器,一个生产线程,当它生产产品(即put的时候),如果当前没有人想要消费产品(即当前没有线程执行take),此生产线程必须阻塞,等待一个消费线程调用take操作,take操作将会唤醒该生产线程,同时消费线程会获取生产线程的产品(即数据传递)
全栈程序员站长
2022/06/25
1.1K0
Java 队列详解
Queue 接口与 List、Set 同一级别,都是继承了 Collection 接口。LinkedList 实现了 Deque接口。
子晋
2022/01/18
7190
Java 队列详解
【面试题精讲】什么是 BlockingQueue?
BlockingQueue 是 Java 并发编程中的一个接口,它表示一个线程安全的、支持阻塞操作的队列。它继承自 java.util.Queue 接口,并在其基础上增加了一些阻塞操作。
程序员朱永胜
2023/10/14
2250
杰哥教你面试之一百问系列:java中高级多线程concurrent的使用
提到多线程,当然要熟悉java提供的各种多线程相关的并发包了,而java.util.concurrent就是最最经常会使用到的,那么关于concurrent的面试题目有哪些呢?一起来看看吧。
程序那些事
2023/09/07
4020
为何我建议你学会Queue集合
PriorityQueue的底层数据结构就如andrewlock.net网站提供的图一样,虽然PriorityQueue是一个平衡二叉堆,但JDK底层的实现却是:一个普普通通的二维数组!!
JavaSouth南哥
2024/09/03
2780
为何我建议你学会Queue集合
Java中的BlockingQueue1 Java中的阻塞队列2 生产者和消费者例子2 Java里的阻塞队列
1 Java中的阻塞队列 1.1 简介 一种支持两个附加操作的队列,是一系列阻塞队列类的接口 当存取条件不满足时,阻塞在操作处 队列满时,阻塞存储元素的线程,直到队列可用 队列空时,获取元素的线程会
JavaEdge
2018/05/16
1.7K0
Java中的LinkedBlockingQueue:原理、应用与性能深入剖析
在Java的并发编程领域,LinkedBlockingQueue是一个非常重要的类,它提供了一种高效且线程安全的方式来处理队列中的元素。该类位于java.util.concurrent包中,是BlockingQueue接口的一个实现,专门设计用于处理多线程环境中的生产者-消费者问题。在本篇博客中,我们将深入探讨LinkedBlockingQueue的内部工作原理、关键特性以及最佳实践。
公众号:码到三十五
2024/03/19
1.3K0
突击并发编程JUC系列-阻塞队列 BlockingQueue
阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作支持阻塞的插入和移除方法。
山间木匠
2020/10/23
6300
突击并发编程JUC系列-阻塞队列 BlockingQueue
10分钟搞定 Java 并发队列好吗?好的
| 好看请赞,养成习惯 你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand i
用户4172423
2020/08/31
6140
10分钟搞定 Java 并发队列好吗?好的
多线程编程学习六(Java 中的阻塞队列).
阻塞队列(BlockingQueue)是指当队列满时,队列会阻塞插入元素的线程,直到队列不满;当队列空时,队列会阻塞获得元素的线程,直到队列变非空。阻塞队列就是生产者用来存放元素、消费者用来获取元素的容器。
JMCui
2021/12/24
5610
多线程编程学习六(Java 中的阻塞队列).
相关推荐
java中的Queue家族详解
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验