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

Java并发基础:SynchronousQueue全面解析! - 程序员古德

内容概要

SynchronousQueue的优点在于其直接性和高效性,它实现了线程间的即时数据交换,无需中间缓存,确保了数据传输的实时性和准确性,同时,其灵活的阻塞机制使得线程同步变得简单而直观,适用于需要精确协调的生产者-消费者模型。

核心概念

假如,有一个在线购物平台,其中有一个非常关键的部分是处理用户的支付请求,当用户点击“支付”按钮后,系统需要确保用户的支付请求能够被安全、快速地处理,并且一旦处理完成,能够立即通知用户支付结果。

在这个场景中,可以将SynchronousQueue看作是一个没有容量的阻塞队列,它严格遵循FIFO(先进先出)的原则,但特殊的是,它不会保存任何元素,而是直接在不同的线程间进行传递。

当用户提交支付请求时,可以创建一个线程(或者使用一个线程池中的线程),该线程负责处理支付逻辑,这个线程会尝试将支付请求放入SynchronousQueue中,但是,由于SynchronousQueue没有容量,这个线程将会被阻塞,直到有另一个线程从队列中取出这个支付请求。

同时,还需有一个或多个线程负责处理支付结果,这些线程会不断地从SynchronousQueue中尝试取出支付请求进行处理,一旦取到支付请求,它们就会开始处理,并将处理结果返回给用户。

使用SynchronousQueue,可以确保支付请求能够按照提交的顺序进行处理,并且处理线程和消费线程之间能够实现高效的同步,当支付请求处理完成后,消费线程可以立即得到通知,并将结果返回给用户,从而提高了系统的响应速度和用户体验。

SynchronousQueue类在Java中主要用于解决线程间的直接、同步的数据交换问题,在多线程编程中,常常会遇到多个线程需要协作完成任务的情况,有时,一个线程需要等待另一个线程提供的数据才能继续执行,此时,使用SynchronousQueue它可以确保数据的生产者和消费者之间严格的同步,即生产者线程在数据被消费者线程取走之前会一直等待,而消费者线程在没有数据可取时也会等待。

这种同步机制有助于避免多线程编程中常见的竞态条件和数据不一致问题,通过SynchronousQueue,可以确保数据在多个线程之间安全、有序地传递,从而提高程序的稳定性和可靠性。

代码案例

下面是一个简单的Java程序,创建了一个生产者线程和一个消费者线程,演示了如何使用SynchronousQueue类,如下代码:

import java.util.concurrent.SynchronousQueue;  
import java.util.concurrent.TimeUnit;  public class SynchronousQueueDemo {  public static void main(String[] args) throws InterruptedException {  // 创建一个SynchronousQueue实例  SynchronousQueue<Integer> queue = new SynchronousQueue<>();  // 创建一个生产者线程  Thread producerThread = new Thread(() -> {  try {  // 模拟生产数据的过程  TimeUnit.SECONDS.sleep(1);  int data = 42; // 假设这是生产的数据  // 将数据放入SynchronousQueue中,如果此时没有消费者线程等待,生产者线程将会被阻塞  queue.put(data);  System.out.println("生产者线程: 数据 " + data + " 已被放入队列。");  } catch (InterruptedException e) {  e.printStackTrace();  }  });  // 创建一个消费者线程  Thread consumerThread = new Thread(() -> {  try {  // 从SynchronousQueue中取出数据,如果没有数据可取,消费者线程将会被阻塞  int data = queue.take();  // 模拟消费数据的过程  TimeUnit.SECONDS.sleep(1);  System.out.println("消费者线程: 数据 " + data + " 已被消费。");  } catch (InterruptedException e) {  e.printStackTrace();  }  });  // 启动生产者和消费者线程  producerThread.start();  consumerThread.start();  // 等待两个线程执行完毕  producerThread.join();  consumerThread.join();  System.out.println("主线程: 程序执行完毕。");  }  
}

在上面的代码中,创建了一个SynchronousQueue实例,并通过它来进行线程间的数据交换。

生产者线程模拟生产数据的过程,并通过put方法将数据放入队列中,如果此时没有消费者线程等待数据,生产者线程将会被阻塞,消费者线程通过take方法从队列中取出数据,并进行消费,如果队列中没有数据可取,消费者线程将会被阻塞。

运行上面的代码,输出如下类似内容:

生产者线程: 数据 42 已被放入队列。  
消费者线程: 数据 42 已被消费。  
主线程: 程序执行完毕。

核心API

SynchronousQueue 是一个没有容量的阻塞队列,每个插入操作必须等待一个相应的删除操作,反之亦然,它主要用于在线程之间进行直接、同步的数据交换,以下是 SynchronousQueue 类中主要方法的含义:

1、put(E e)

  • 将指定的元素插入此队列中,如果另一个线程正在等待接收它,则立即将其移交给该线程,否则等待直到有线程来取。
  • 由于 SynchronousQueue 是一个没有容量的队列,put 方法将会阻塞直到有消费者线程通过 takepoll 方法来移除这个元素。

2、take()

  • 移除并返回此队列的头部,在元素变得可用之前一直等待。
  • 如果没有元素可用,take 方法将会阻塞直到有生产者线程通过 put 方法来提供一个元素。

3、offer(E e)

  • 将指定的元素插入此队列中,如果另一个线程正在等待接收它,则立即将其移交给该线程,并返回 true,否则立即返回 false
  • 这个方法是非阻塞的,如果队列中没有等待的消费者,它会立即返回 false

4、offer(E e, long timeout, TimeUnit unit)

  • 将指定的元素插入此队列中,等待指定的时间以使另一个线程接收它,如果在指定的时间内没有线程等待,则返回 false
  • 这个方法允许生产者在放弃之前等待一段时间,以看是否有消费者线程能够接收元素。

5、poll()

  • 移除并返回此队列的头部,如果此队列为空,则返回 null
  • 这个方法是非阻塞的,它立即返回队列中的头部元素,如果队列为空则返回 null

6、poll(long timeout, TimeUnit unit)

  • 移除并返回此队列的头部,在指定的时间内等待元素变得可用,如果在指定的时间内队列仍然为空,则返回 null
  • 这个方法允许消费者在放弃之前等待一段时间,以看是否有生产者线程能够提供元素。

7、peek()

  • 检索但不移除此队列的头部,如果此队列为空,则返回 null
  • 这个方法是非阻塞的,它仅仅查看队列的头部而不移除它。

8、isEmpty()

  • 检查此队列是否为空。
  • 对于 SynchronousQueue 来说,这个方法可能不是特别有用,因为它没有容量,且其状态是瞬时的,可能在调用此方法后立即改变。

9、clear()

  • 由于 SynchronousQueue 是一个没有容量的队列,此方法实际上没有什么可做的,调用它不会有任何效果。

10、remainingCapacity()

  • 对于 SynchronousQueue,此方法始终返回 0,因为队列没有容量。

11、drainTo(Collection<? super E> c)

  • 将此队列中所有可用的元素都移除,并将它们添加到给定的集合中。
  • 由于 SynchronousQueue 是一个没有容量的队列,这个方法通常不会移除任何元素,除非在调用此方法时恰好有元素在等待被消费。

12、drainTo(Collection<? super E> c, int maxElements)

  • 将此队列中最多给定数量的可用元素移除,并将它们添加到给定的集合中。
  • drainTo(Collection<? super E> c) 方法类似,但由于 SynchronousQueue 的特性,这个方法通常也不会移除任何元素。

核心总结

Java并发基础:SynchronousQueue全面解析! - 程序员古德

SynchronousQueue类是一个无缓冲的、基于阻塞的队列,专门用于线程间的数据传输,它的主要优点体现在其高效性和直接性上:

优点:

  1. 高效性:直接传递对象,不需要像其他队列那样进行数据的复制或移动,从而提高了数据传输的效率。
  2. 直接性:每个插入操作都必须等待一个相应的删除操作,反之亦然,这使得线程间的数据交换更加直接和明确。
  3. 灵活性:通过puttake方法的结合使用,可以在生产者线程和消费者线程之间实现灵活的同步。

缺点:

  1. 阻塞性:由于SynchronousQueue的无缓冲特性,当没有匹配的生产者或消费者线程时,线程会被阻塞,这可能导致性能下降。

使用建议:

  1. 适用于低延迟场景:适用于需要低延迟的线程间通信场景,如生产者-消费者模型中的精确同步。
  2. 避免长时间等待:在使用SynchronousQueue时,应尽量避免线程长时间等待,可以通过设置合理的超时时间或使用其他同步机制来优化。

END!
END!
END!

往期回顾

精品文章

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

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

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

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

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

精彩视频

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/683886.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

相机图像质量研究(13)常见问题总结:光学结构对成像的影响--鬼影

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…

二级 C 语言笔试-15

一、选择题 1. 程序流程图中带有箭头的线段表示的是( )。 A) 图元关系 B) 数据流 C) 控制流 D) 调用关系 2. 下列描述中正确的是( )。 A) 程序就是软件 B) 软件开发不受计算机系统的限制 C) 软件既是逻辑实体&#xff0c;又是物理实体 D) 软件是程序、数据与相关文档的集合 3. …

人类智能与人工智能之间有泰勒公式的味道

人工智能&#xff08;AI&#xff09;与人类智能之间的关系&#xff0c;简单类比为泰勒公式可能并不准确&#xff0c;但在某种程度上或许有些味道。 泰勒公式是一种数学工具&#xff0c;用于将一个函数在某个点附近展开成无穷级数的形式&#xff0c;以近似描述函数的行为。它通过…

TiDB 在医疗保障信息平台的应用实践

文章介绍了 TiDB 在医疗保障信息平台中的应用。东软医保云应用管理平台通过与 TiDB 联合&#xff0c;成功满足了医疗保障业务中高并发、实时性和复杂查询的要求。在某地市医疗保障信息平台的实践中&#xff0c;TiDB 分布式数据库有效实现了在线交易和实时分析服务&#xff0c;日…

C语言学习day14:数组定义和使用

定义变量&#xff1a; 数据类型 变量 值 数组定义&#xff1a; 数据类型 数组名[元素个数]{值1,值2,值3} 代码&#xff1a; int main() {//定义变量//数据类型 变量 值//数组定义//数据类型 数组名[元素个数]{值1,值2,值3}//数组下标 数组名[小标]//数组下标是…

sql深度优化

sql优化是一个大家都比较关注的热门话题&#xff0c;无论在面试&#xff0c;还是工作中&#xff0c;都很有可能会遇到。 如果某天负责的某个线上接口&#xff0c;出现了性能问题&#xff0c;需要做优化。那么你首先想到的很有可能是优化sql语句&#xff0c;因为它的改造成本相对…

.NET Core WebAPI中封装Swagger配置

一、创建相关文件 创建一个Utility/SwaggerExt文件夹&#xff0c;添加一个类 二、在Program中找到Swagger相关配置信息 三、添加方法&#xff0c;在Program中调用 在SwaggerExt类中添加方法&#xff0c;将相关配置添写入 /// <summary> /// swagger配置 /// </sum…

初识Qt | 从安装到编写Hello World程序

文章目录 1.前端开发简单分类2.Qt的简单介绍3.Qt的安装和环境配置4.创建简单的Qt项目 1.前端开发简单分类 前端开发&#xff0c;这里是一个广义的概念&#xff0c;不单指网页开发&#xff0c;它的常见分类 网页开发&#xff1a;前端开发的主要领域&#xff0c;使用HTML、CSS …

C++函数对象-运算符函数对象 - 位运算 - 实现 x ^ y 的函数对象 (std::bit_xor)

任何定义了函数调用操作符的对象都是函数对象。C 支持创建、操作新的函数对象&#xff0c;同时也提供了许多内置的函数对象。 运算符函数对象 C 针对常用的算术和逻辑运算定义了很多函数对象&#xff1a; 位运算 实现 x ^ y 的函数对象 std::bit_xor template< class T &…

[经验] 欧阳修唐宋八大家之首是谁 #微信#知识分享#学习方法

欧阳修唐宋八大家之首是谁 1、唐宋八大家之首是谁 唐宋八大家是中国文学史上最具代表性的八位大文豪&#xff0c;他们的文学成就在中国文学史上占有重要地位&#xff0c;被誉为文学史上的“巨人”。 唐宋八大家之首&#xff0c;无疑是唐代著名诗人杜甫。他出生在一个贫苦的家…

牛客——IncDec Sequence(差分)

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 题目描述 给定一个长度为 n(n≤105)(n \leq 10^5 )(n≤105) 的数列a1,a2,…,an{a_1,a_2,…,a_n}a1​,a2​,…,an​&#xff0c;每次可以选择一个区间 [l,r]&#xff0c;使下标在这个区间内的数…

每日一题 力扣107 二叉树的层序遍历Ⅱ

107. 二叉树的层序遍历 II 题目描述&#xff1a; 给你二叉树的根节点 root &#xff0c;返回其节点值 自底向上的层序遍历 。 &#xff08;即按从叶子节点所在层到根节点所在的层&#xff0c;逐层从左向右遍历&#xff09; 示例 1&#xff1a; 输入&#xff1a;root [3,9,20…

如何用 ChatGPT 做项目管理?

ChatGPT 可以通过创建和维护跨团队项目协作计划&#xff0c;让员工更容易理解他们的角色和职责。 这个协作计划里面会包括每个团队或个人要执行的具体任务&#xff0c;每个任务最后期限和任何事情之 间的依赖关系。 该场景对应的关键词库:(24 个) 项目管理、项目协作计划、跨…

操作 Docker 存储卷的常用指令汇总

1. 什么是存储卷&#xff1f; 存储卷就是将宿主机的本地文件系统中存在的某个目录直接与容器内部的文件系统上的某一目录建立绑定关系。使得可以在宿主机和容器内共享数据库内容&#xff0c;让容器直接访问宿主机中的内容&#xff0c;也可以宿主机向容器写入内容&#xff0c;容…

(通信)驻波

驻波是一种物理现象&#xff0c;它发生在频率相同、传输方向相反的两种波&#xff08;不一定是电波&#xff09;沿传输线形成的一种分布状态。 在这种状态下&#xff0c;一个波通常是另一个波的反射波。 在驻波中&#xff0c;波节和波腹的位置始终保持不变&#xff0c;给人一种…

了解Ping、Wget、端口、Netstat和Curl命令

1. 端口 1.1 什么是端口&#xff1f; 端口是一种用于标识不同应用程序或服务的逻辑通道。它是一个数字&#xff0c;取值范围从0到65535。常见的端口有一些已经被标准化&#xff0c;比如HTTP使用的80端口&#xff0c;HTTPS使用的443端口。 1.2 了解端口状态 使用netstat -an…

【深度学习】Pytorch 系列教程(二):PyTorch数据结构:1、Tensor(张量): GPU加速(GPU Acceleration)

文章目录 一、前言二、实验环境三、PyTorch数据结构0、分类1、Tensor&#xff08;张量&#xff09;1. 维度&#xff08;Dimensions&#xff09;2. 数据类型&#xff08;Data Types&#xff09;3. GPU加速&#xff08;GPU Acceleration&#xff09;查看可用gpu张量移动经典语句d…

边缘计算第二版施巍松——第8章边缘计算系统实例

8.1边缘计算系统概述 1.Cloudlet 架构&#xff1a;移动设备-Cloudlet-云 cloudlet也可以像云一样为用户提供服务&#xff0c;Cloudlet离移动设备只有一跳的距离&#xff0c;具有物理距离的临近性&#xff0c;可以保证实时反馈时延低&#xff0c;又可以利用局域网的高带宽优势&…

(五)【Jmeter】使用代理录制HTTP脚本操作步骤及注意事项

前置信息 软件版本Jmeter5.6.3 服务网址备注drupalhttp://192.168.88.88:18080/&#xff08;二&#xff09;【Jmeter】专栏实战项目靶场drupal部署 用户名密码test1test1test2test2 实操记录 1、启动jmeter&#xff0c;操作顺序见下图 2、在视图面板添加如下信息&#x…

Elcomsoft 取证工具包系列:Advanced SQL Password Recovery

天津鸿萌科贸发展有限公司是 Elcomsoft 系列软件的授权代理商。Elcomsoft 取证工具包系列软件提供了一系列强大丰富的密码恢复功能&#xff0c;为取证工作打开一道道畅通的大门&#xff0c;是取证工作者必备的工具。 Advanced SQL Password Recovery 高级 SQL 密码恢复软件 即…