热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

java并发编程工具类JUC第六篇:SynchronousQueue同步队列

在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口、ArrayBlockingQueue、DelayQueue、LinkedBlockingQue

java并发编程工具类JUC第六篇:SynchronousQueue同步队列


在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口、ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue、PriorityBlockingQueue,本文为系列文章第六篇。

本篇文章将为大家介绍并发编程集合类SynchronousQueue,它是BlockingQueue接口的实现类。与所有的BlockingQueue接口实现类不同的是:SynchronousQueue队列的容量永远是0(或者可以理解为容量为1的队列,但是说队列容量为1并不准确),这是因为SynchronousQueue实际上它不是一个真正的队列,因为它不会为队列中元素维护存储空间,它只是多个线程之间数据交换的媒介。

  • SynchronousQueue队列的一个线程的插入动作总是会等待另一个线程的移除操作,反之亦然。
  • put()方法放入元素对象到 SynchronousQueue不会返回结果(处于阻塞状态),直到另一个线程执行take()移除元素对象.
  • peek()方法在BlockingQueue接口实现类中可以获取元素,但不从队列中移除该元素。但在SynchronousQueue队列中该方法不可用。

SynchronousQueue 同步队列例子

下面我们写一个例子,来帮助我们理解SynchronousQueue的特性及用法。
SynchronousQueueProducer.java 启动线程每隔一秒向队列中放入一个Integer对象。

public class SynchronousQueueProducer implements Runnable {

   protected BlockingQueue blockingQueue;
   public SynchronousQueueProducer(BlockingQueue queue) {
      this.blockingQueue = queue;
   }

   @Override
   public void run() {
      int i = 0;
      while (true) {
         System.out.println(Thread.currentThread().getName() + " Put: " + ++i);
         try {
            blockingQueue.put(i);
            Thread.sleep(1000);  //每隔一秒生产一次
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }

}

SynchronousQueueConsumer.java启动线程每5秒从队列中取出一个元素对象。

public class SynchronousQueueConsumer implements Runnable {
   protected BlockingQueue blockingQueue;

   public SynchronousQueueConsumer(BlockingQueue queue) {
      this.blockingQueue = queue;
   }

   @Override
   public void run() {
      while (true) {
         try {
            Integer data = blockingQueue.take();
            System.out.println(Thread.currentThread().getName() + " take(): " + data);
            Thread.sleep(5000);  //每隔5秒消费一次
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }

}

SynchronousQueueExample.java 新建一个SynchronousQueue同步队列,启动一个生产者线程插入对象,两个消费者线程移除对象。进行测试,看看效果。


public class SynchronousQueueExample {
    public static void main(String[] args) {
      final BlockingQueue synchrOnousQueue= new SynchronousQueue<>();
    
      SynchronousQueueProducer queueProducer = new SynchronousQueueProducer(synchronousQueue);
      new Thread(queueProducer).start();
    
      SynchronousQueueConsumer queueConsumer1 = new SynchronousQueueConsumer(synchronousQueue);
      new Thread(queueConsumer1).start();
    
      SynchronousQueueConsumer queueConsumer2 = new SynchronousQueueConsumer(synchronousQueue);
      new Thread(queueConsumer2).start();
    }
}

分析一下实验的结果,Thread-0 是生产者线程,Thread-1 和 Thread-2是消费者线程。从实验结果我们可以看到SynchronousQueue必须是生产一次、消费一次、生产一次、消费一次,不论有多少个消费者和生产者线程都必须遵循这个规则。

Thread-0 Put: 1
Thread-1 take(): 1
Thread-0 Put: 2
Thread-2 take(): 2
Thread-0 Put: 3
Thread-1 take(): 3
Thread-0 Put: 4
Thread-2 take(): 4
Thread-0 Put: 5
Thread-1 take(): 5
Thread-0 Put: 6
Thread-2 take(): 6
Thread-0 Put: 7
Thread-1 take(): 7
Thread-0 Put: 8
Thread-2 take(): 8
Thread-0 Put: 9
Thread-1 take(): 9
Thread-0 Put: 10
Thread-2 take(): 10
Thread-0 Put: 11
Thread-1 take(): 11
Thread-0 Put: 12
Thread-2 take(): 12

应用场景:如果我们不确定来自生产者请求数量,但是这些请求需要很快的处理掉,那么配合SynchronousQueue为每个生产者请求分配一个消费线程是最处理效率最高的办法。Executors.newCachedThreadPool()底层就使用了SynchronousQueue,这个线程池根据需求创建新的线程。

欢迎关注我的博客,里面有很多精品合集

  • 本文转载注明出处(必须带连接,不能只转文字):字母哥博客。

觉得对您有帮助的话,帮我点赞、分享!您的支持是我不竭的创作动力! 。另外,笔者最近一段时间输出了如下的精品内容,期待您的关注。

  • 《手摸手教你学Spring Boot2.0》
  • 《Spring Security-JWT-OAuth2一本通》
  • 《实战前后端分离RBAC权限管理系统》
  • 《实战SpringCloud微服务从青铜到王者》
  • 《VUE深入浅出系列》

推荐阅读
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 标题: ... [详细]
  • 在springmvc框架中,前台ajax调用方法,对图片批量下载,如何弹出提示保存位置选框?Controller方法 ... [详细]
  • Spring学习(4):Spring管理对象之间的关联关系
    本文是关于Spring学习的第四篇文章,讲述了Spring框架中管理对象之间的关联关系。文章介绍了MessageService类和MessagePrinter类的实现,并解释了它们之间的关联关系。通过学习本文,读者可以了解Spring框架中对象之间的关联关系的概念和实现方式。 ... [详细]
  • 网络请求模块选择——axios框架的基本使用和封装
    本文介绍了选择网络请求模块axios的原因,以及axios框架的基本使用和封装方法。包括发送并发请求的演示,全局配置的设置,创建axios实例的方法,拦截器的使用,以及如何封装和请求响应劫持等内容。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
author-avatar
dongquchunlaizv_123
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有