并发容器:阻塞队列之SynchronousQueue

1 介绍

SynchronousQueue也是实现自BlockingQueue的一个阻塞队列,每一次对其的写入操作必须等待(阻塞)其他线程进行对应的移除操作,SynchronousQueue的内部并不会涉及容量、获取size,就连peek方法的返回值永远都将会是null,除此之外还有更多的方法在SynchronousQueue中也都未提供对应的支持(列举如下),因此在使用的过程中需要引起注意,否则会使得程序的运行出现不符合预期的错误。

  • clear():清空队列的方法在SynchronousQueue中不起任何作用。
  • contains(Object o):永远返回false。
  • containsAll(Collection<?> c):等价于c是否为空的判断。
  • isEmpty():永远返回true。
  • iterator():返回一个空的迭代器。
  • peek():永远返回null。
  • remainingCapacity():始终返回0。
  • remove(Object o):不做任何删除,并且始终返回false。
  • removeAll(Collection<?> c):不做任何删除,始终返回false。
  • retainAll(Collection<?> c):始终返回false。
  • size():返回值始终为0。
  • spliterator():返回一个空的Spliterator
  • toArray()及toArray(T[] a)方法同样也不支持。

看起来好多方法在SynchronousQueue中都不提供对应的支持,那么SynchronousQueue是一个怎样的队列呢?简单来说,我们可以借助于SynchronousQueue在两个线程间进行线程安全的数据交换

主要作用在于在两个线程之间进行数据交换,区别于Exchanger的主要地方在于(站在使用的角度)SynchronousQueue所涉及的一对线程一个更加专注于数据的生产,另一个更加专注于数据的消费(各司其职),而Exchanger则更加强调一对线程数据的交换。

SynchronousQueue在日常的开发使用中并不是很常见,即使在JDK内部,该队列也仅用于ExecutorService中的Cache Thread Pool创建

2 代码示例:数据交换

public class SynchronousQueueTest {


    public static void main(String[] args) {
        // 定义String类型的SynchronousQueue
        SynchronousQueue<String> queue = new SynchronousQueue<>();
        // 定义两个线程,写入数据
        IntStream.rangeClosed(0, 1).forEach(i->{
            new Thread(()->{
                try {
                    // 若没有对应的数据消费线程,则put方法将会导致当前线程进入阻塞
                    queue.put(Thread.currentThread().getName());
                    System.out.println(Thread.currentThread().getName() + " put data -> " + Thread.currentThread().getName());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            },"P-" +i).start();
        });

        // 启动两个线程从queue中消费数据
        IntStream.rangeClosed(0, 1).forEach(i->{
            new Thread(()->{
                try {
                    // 若没有对应的数据生产线程,则take方法将会导致当前线程进入阻塞
                    String data = queue.take();
                    System.out.println(Thread.currentThread().getName() + " take data -> " + data);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            },"C-" +i).start();
        });
    }
}
C-0 take data -> P-1
C-1 take data -> P-0
P-0 put data -> P-0
P-1 put data -> P-1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值