Java中的SynchronousQueue队列详解

 更新时间:2023年12月07日 09:00:33   作者:flydean程序那些事  
这篇文章主要介绍了Java中的SynchronousQueue队列详解,SynchronousQueue是BlockingQueue的一种,所以SynchronousQueue是线程安全的,SynchronousQueue和其他的BlockingQueue不同的是SynchronousQueue的capacity是0,需要的朋友可以参考下

简介

SynchronousQueue是BlockingQueue的一种,所以SynchronousQueue是线程安全的。

SynchronousQueue和其他的BlockingQueue不同的是SynchronousQueue的capacity是0。

即SynchronousQueue不存储任何元素。

也就是说SynchronousQueue的每一次insert操作,必须等待其他线性的remove操作。

而每一个remove操作也必须等待其他线程的insert操作。

这种特性可以让我们想起了Exchanger。和Exchanger不同的是,使用SynchronousQueue可以在两个线程中传递同一个对象。

一个线程放对象,另外一个线程取对象。

举例说明

我们举一个多线程中传递对象的例子。

还是举生产者消费者的例子,在生产者中我们创建一个对象,在消费者中我们取出这个对象。

先看一下用CountDownLatch该怎么做:

    @Test
    public void useCountdownLatch() throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(2);
        AtomicReference<Object> atomicReference= new AtomicReference<>();
        CountDownLatch countDownLatch = new CountDownLatch(1);

        Runnable producer = () -> {
            Object object=new Object();
            atomicReference.set(object);
            log.info("produced {}",object);
            countDownLatch.countDown();
        };

        Runnable consumer = () -> {
            try {
                countDownLatch.await();
                Object object = atomicReference.get();
                log.info("consumed {}",object);
            } catch (InterruptedException ex) {
                log.error(ex.getMessage(),ex);
            }
        };

        executor.submit(producer);
        executor.submit(consumer);

        executor.awaitTermination(50000, TimeUnit.MILLISECONDS);
        executor.shutdown();
    }

上例中,我们使用AtomicReference来存储要传递的对象,并且定义了一个型号量为1的CountDownLatch。

在producer中,我们存储对象,并且countDown。

在consumer中,我们await,然后取出对象。

输出结果:

[pool-1-thread-1] INFO com.flydean.SynchronousQueueUsage - produced java.lang.Object@683d1b4b
[pool-1-thread-2] INFO com.flydean.SynchronousQueueUsage - consumed java.lang.Object@683d1b4b

可以看到传入和输出了同一个对象。

上面的例子我们也可以用SynchronousQueue来改写:

    @Test
    public void useSynchronousQueue() throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(2);
        SynchronousQueue<Object> synchronousQueue=new SynchronousQueue<>();
        Runnable producer = () -> {
            Object object=new Object();
            try {
                synchronousQueue.put(object);
            } catch (InterruptedException ex) {
                log.error(ex.getMessage(),ex);
            }
            log.info("produced {}",object);
        };
        Runnable consumer = () -> {
            try {
                Object object = synchronousQueue.take();
                log.info("consumed {}",object);
            } catch (InterruptedException ex) {
                log.error(ex.getMessage(),ex);
            }
        };
        executor.submit(producer);
        executor.submit(consumer);
        executor.awaitTermination(50000, TimeUnit.MILLISECONDS);
        executor.shutdown();
    }

上面的例子中,如果我们使用synchronousQueue,则可以不用手动同步,也不需要额外的存储。

总结

如果我们需要在代码中用到这种线程中传递对象的情况,那么使用synchronousQueue吧。

到此这篇关于Java中的SynchronousQueue队列详解的文章就介绍到这了,更多相关SynchronousQueue队列内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot环境下junit单元测试速度优化方式

    SpringBoot环境下junit单元测试速度优化方式

    这篇文章主要介绍了SpringBoot环境下junit单元测试速度优化方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • SpringBoot配置shiro安全框架的实现

    SpringBoot配置shiro安全框架的实现

    这篇文章主要介绍了SpringBoot配置shiro安全框架的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • 如何使用MAVEN打JAR包(直接使用)

    如何使用MAVEN打JAR包(直接使用)

    这篇文章主要介绍了如何使用MAVEN打JAR包(直接使用),文中通过实例代码介绍了maven 使用assembly插件进行打包的方法,需要的朋友可以参考下
    2023-03-03
  • 面向对象和面向过程的区别(动力节点java学院整理)

    面向对象和面向过程的区别(动力节点java学院整理)

    很多朋友不清楚面向对象和面向过程有什么区别,接下来小编给大家整理了关于面向对象和面向过程的区别讲解,感兴趣的朋友可以参考下
    2017-04-04
  • java中Map和List初始化的N种方法总结

    java中Map和List初始化的N种方法总结

    这篇文章主要介绍了java中Map和List初始化的N种方法总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • 彻底解决Spring MVC中文乱码问题的方案

    彻底解决Spring MVC中文乱码问题的方案

    这篇文章主要介绍了彻底解决Spring MVC中文乱码问题的方案,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2016-11-11
  • Java如何导出包含多个Sheet的Excel文件

    Java如何导出包含多个Sheet的Excel文件

    这篇文章主要为大家详细介绍了Java如何导出包含多个Sheet的Excel文件,文中一共介绍了两种实现方法,有需要的小伙伴可以跟随小编一起学习一下
    2025-07-07
  • JavaIO模型中的BIO,NIO和AIO详解

    JavaIO模型中的BIO,NIO和AIO详解

    这篇文章主要为大家详细介绍了JavaIO模型中的BIO,NIO和AIO,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • Spring加载XSD文件发生错误的解决方法

    Spring加载XSD文件发生错误的解决方法

    这篇文章主要介绍了Spring加载XSD文件发生错误的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-08-08
  • SpringBoot中@Value注入静态变量方式

    SpringBoot中@Value注入静态变量方式

    SpringBoot中静态变量无法直接用@Value注入,需通过setter方法,@Value('${}')从属性文件获取值,@Value('#{}')用于SpEL表达式,可注入其他bean属性,注意bean默认名称为类名首字母小写
    2025-08-08

最新评论