SynchronousQueue是BlockingQueue的一种特殊类型,其中每个插入操作必须等待另一个线程进行相应的删除操作,反之亦然。 当您在SynchronousQueue上调用put()方法时,它将阻塞,直到有另一个线程将该元素从Queue中取出为止。 同样,如果一个线程尝试删除一个元素并且当前不存在任何元素,则该线程将被阻塞,直到另一个线程将一个元素放入队列中为止。 您可以将SynchronousQueue与运行奥运火炬的运动员( 线程 )相关联,使他们运行火炬(需要传递对象)并将其传递给在另一端等待的其他运动员。 如果您注意该名称,您还将了解到它被命名为SynchronousQueue是有原因的,它将数据同步传递到其他线程。 它等待对方获取数据,而不仅仅是放入数据并返回(异步操作)。 如果您熟悉CSP和Ada,那么您就会知道同步队列类似于集合通道。 它们非常适合切换设计,在该设计中,在一个线程中运行的对象必须与在另一个线程中运行的对象同步,以便向其传递一些信息,事件或任务。 在早期的多线程教程中,我们学习了如何使用wait and notify和BlockingQueue解决生产者消费者问题,在本教程中,我们将学习如何使用同步队列来实现生产者消费者设计模式 。 此类还支持用于订购等待的生产者和使用者线程的可选公平性策略。 默认情况下,不保证此排序。 但是,将Fairness属性设置为true构造的队列将按FIFO顺序授予线程访问权限。

正如我之前说过的,没有什么比生产者使用者问题更好地理解任何编程语言中的线程间通信了。 在生产者使用者问题中,一个线程充当产生事件或任务的生产者,而另一个线程充当使用者。 共享缓冲区用于将数据从生产者传输到消费者。 解决生产者使用者问题的困难在于边缘情况,例如,如果缓冲区已满,生产者必须等待,如果缓冲区为空,使用者线程必须等待。 后来一个很容易,因为阻塞队列不仅提供缓冲区来存储数据,而且还提供流控制来阻塞线程,如果缓冲区已满,则调用put()方法(PRODUCER),如果阻塞为空,则阻塞线程将调用take()方法(CONSUMER) 。 在本教程中,我们将使用SynchronousQueue(一种零容量的特殊并发集合)解决相同的问题。

在下面的示例中,我们有两个线程,分别名为PRODUCER和CONSUMER(您应始终命名线程,这是编写并发应用程序的最佳实践之一)。 第一线程,发布板球得分,第二线程正在消耗它。 板球比分不过是一个String对象。 如果您按原样运行程序,则不会发现任何不同。 为了了解SynchronousQueue的工作原理以及如何解决生产者使用者问题 ,您需要在Eclipse中调试该程序,或者只是通过注释consumer.start()来启动生产者线程。 如果使用者线程未运行,则生产者将在以下位置阻塞
队列。 put(event); 通话,您将不会看到[PRODUCER]发布的活动:四个。 发生这种情况是由于 SynchronousQueue,它确保线程插入数据将一直阻塞,直到有线程删除该数据为止,反之亦然。 您可以通过注释生产者来测试代码的另一部分。 开始(); 并且仅启动使用者线程。

import java.util.concurrent.SynchronousQueue;/*** Java Program to solve Producer Consumer problem using SynchronousQueue. A* call to put() will block until there is a corresponding thread to take() that* element.** @author Javin Paul*/
public class SynchronousQueueDemo{public static void main(String args[]) {final SynchronousQueue<String> queue = new SynchronousQueue<String>();Thread producer = new Thread("PRODUCER") {public void run() {String event = "FOUR";try {queue.put(event); // thread will block hereSystem.out.printf("[%s] published event : %s %n", Thread.currentThread().getName(), event);} catch (InterruptedException e) {e.printStackTrace();}}};producer.start(); // starting publisher threadThread consumer = new Thread("CONSUMER") {public void run() {try {String event = queue.take(); // thread will block hereSystem.out.printf("[%s] consumed event : %s %n", Thread.currentThread().getName(), event);} catch (InterruptedException e) {e.printStackTrace();}}};consumer.start(); // starting consumer thread}}Output:
[CONSUMER] consumed event : FOUR
[PRODUCER] published event : FOUR

如果您仔细发送了输出,那么您会注意到事件的顺序是相反的。 似乎[CONSUMER]线程正在消耗数据,甚至在[PRODUCER]线程产生数据之前。 发生这种情况是因为默认情况下,SynchronousQueue不保证任何顺序,但是它具有公平性策略,如果将其设置为true,则可以按FIFO顺序访问线程。 您可以通过将true传递给SynchronousQueue的重载构造函数 (即新的SynchronousQueue(boolean fair))来启用此公平性策略。

这是Java中此特殊阻塞队列的一些重要属性。 将数据从一个线程同步传输到另一个线程非常有用。 它没有任何容量,只有在另一端有线程时才阻塞。

  1. SynchronousQueue阻塞,直到另一个线程准备好接受该元素,一个线程正在尝试放置该元素。
  2. SynchronousQueue的容量为零。
  3. SynchronousQueue用于实现直接切换的排队策略,在该策略中,线程将切换到等待的线程,否则允许创建新线程,否则拒绝任务。
  4. 此队列不允许使用null元素,添加null元素将导致NullPointerException 。
  5. 出于其他Collection方法(例如contains)的目的,SynchronousQueue充当空集合。
  6. 您无法窥视同步队列,因为仅当您尝试删除它时,该元素才存在。 同样,您不能插入元素(使用任何方法),除非另一个线程试图将其删除。
  7. 您无法在SynchronousQueue上进行迭代,因为没有要进行迭代的内容。
  8. 将公平性策略设置为true构造的SynchronousQueue授予线程按FIFO顺序的访问权限。

这就是Java中的SynchronousQueue 。 我们已经看到了此特殊并发集合的某些特殊属性,并学习了如何使用Java中的SynchronousQueue解决经典的生产者使用者问题。 顺便说一下,队列有点令人困惑,因为它没有任何能力容纳您的元素。 在有一个线程正在调用take()操作之前,对put()操作的调用不会完成。 最好是线程之间共享对象的集合点。 换句话说,它是一个实用程序,可以在Java中的两个线程之间同步共享数据,这可能是更安全的wait和notify方法的替代方法。

翻译自: https://www.javacodegeeks.com/2014/06/synchronousqueue-example-in-java-producer-consumer-solution.html

Java中的SynchronousQueue示例–生产者使用者解决方案相关推荐

  1. java中get接口示例_Java即时类| 带示例的get()方法

    java中get接口示例 即时类的get()方法 (Instant Class get() method) get() method is available in java.time package ...

  2. java中get接口示例_Java LocalDateTime类| 带示例的get()方法

    java中get接口示例 LocalDateTime类的get()方法 (LocalDateTime Class get() method) get() method is available in ...

  3. Java中常见的URL问题及解决方案

    Java中常见的URL问题及解决方案 参考文章: (1)Java中常见的URL问题及解决方案 (2)https://www.cnblogs.com/lampbrotherIT/p/5680460.ht ...

  4. 设计模式-单例模式-注册式单例模式-枚举式单例模式和容器式单例模式在Java中的使用示例

    场景 设计模式-单例模式-饿汉式单例模式.懒汉式单例模式.静态内部类在Java中的使用示例: 设计模式-单例模式-饿汉式单例模式.懒汉式单例模式.静态内部类在Java中的使用示例_霸道流氓气质的博客- ...

  5. Java中关于内存泄漏分析和解决方案,都在这里了!

    作者:李序锴 www.jianshu.com/p/54b5da7c6816 最近正在熟悉Java内存泄漏的相关知识,上网查阅了一些资料,在此做个整理算是对收获的一些总结,希望能对各位有所帮助,有问题可 ...

  6. java中po代码示例_java操作oracle常用的示例代码详解

    import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sq ...

  7. redistemplate hash 过期时间_完美!谈谈Java中时间控制的几种解决方案

    前言 需求是这样的,在与第三方对接过程中,对方提供了token进行时效性验证,过一段时间token就会失效.后台有定时任务在获取,但是偶尔会出现token失效,这是因为在获取的时候,定时任务正在跑,可 ...

  8. Java中replaceAll去除不掉空格解决方案

    项目场景: 解压解析一个上传的压缩包下的word,存入数据库 问题描述: 存入数据库某描述字段时发现有乱码 "?" 的存入,经排查后发现是一个空格导致的,于是想要把存储的内容进行去 ...

  9. Java中使用ArrayList的10个示例–教程

    Java中的ArrayList是HashMap之后最常用的集合类. Java ArrayList表示一个可自动调整大小的数组,并用于代替数组. 由于创建数组后我们无法修改数组的大小,因此我们更喜欢在J ...

最新文章

  1. 一套完整的数字无线监控系统需要哪些设备和材料?
  2. spring注解@Component、@Repository、@Service、@Controller
  3. C++ operator两种用法【转】
  4. poj1195 Mobile phones 二维线段树入门
  5. [Mac入门]如何在Mac下显示Finder中的所有文件
  6. SaltStack实战之远程执行-Modules
  7. python pandas csv时间聚合_pandas中简单统计分组聚合函数的介绍
  8. 国潮宫廷中国风文创包装品牌样机
  9. Axure电脑web端通用元件库rplib文件格式+移动端app通用元件库rplib文件格式(内含使用教程)
  10. 幼儿园带括号算式口诀_幼教必备:幼儿园17首数学儿歌收藏!
  11. mysql database table_mysqldump database table
  12. 数字化转型背景下的金融交易业务中台实践
  13. PHP - 日期和时间
  14. sqlmap使用教程
  15. CoolFire系列讲座 第7讲
  16. 美国工程管理计算机方向,理工科同学必看!美国工程管理研究生申请大揭秘~...
  17. WLT8016:模组通信调试
  18. 南方cass计算表面积_CASS-工程应用“计算表面积”教程
  19. 信息技术前言讲座报告
  20. 1.3 项目经理的知识和技能

热门文章

  1. mysql自动插入的时间不对 差8小时
  2. ssm执行linux 指令,Linux逻辑卷快照及ssm的使用
  3. mysql级联复制转换成一主两从_一主两从转级联复制
  4. 笨办法学习@ConditionalOnProperty 烧脑配置记录
  5. 对于高并发的理解及实践方案
  6. kafka mirror_SSL Kafka经纪人从Kafka Mirror Maker迁移到Brooklin的挑战
  7. pcl_openmap_OpenMap教程第2部分–使用MapHandler构建基本地图应用程序–第1部分
  8. java代理模式_Java代理
  9. cassandra_Apache Cassandra和低延迟应用程序
  10. 如何使用Java创建AWS Lambda函数