SynchronousQueue简介

本文介绍了Java中的SynchronousQueue,一种无容量队列,用于线程间同步数据传输,可能导致死锁。通过示例演示了其工作原理及潜在的死锁问题,强调了正确设计和同步的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、介绍:

  • SynchronousQueue 是一个具有零容量的队列,它不保存任何元素,它的主要作用是在线程之间传递数据。
  • 当生产者线程尝试将数据放入 SynchronousQueue 时,它会阻塞,直到有一个消费者线程来获取这个数据。
  • 同样地,当消费者线程尝试从 SynchronousQueue 获取数据时,它也会阻塞,直到有一个生产者线程将数据放入队列。

二、使用demo:

public class Test {

    public static void main(String[] args) {

        Logger log = LoggerFactory.getLogger(Test.class);


        SynchronousQueue<Integer> integers = new SynchronousQueue<>();
        new Thread(() -> {
            try {
                log.info("putting {} ", 1);
                integers.put(1);
                log.info("{} putted...", 1);
                log.info("putting...{} ", 2);
                integers.put(2);
                log.info("{} putted...", 2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "t1").start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        new Thread(() -> {
            try {
                log.info("taking {}", 1);
                integers.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "t2").start();

   /*     try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        new Thread(() -> {
            try {
                log.info("taking {}", 2);
                integers.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "t3").start();*/
    }
}

可以得出结论:如果没有消费者来消费, 2 是不能放入 SynchronousQueue 队列中的;
将注释的代码打开,则 2 可以正常放入 !!!
在这里插入图片描述

三、死锁的场景

需要注意的是,SynchronousQueue 的使用需要谨慎,因为它非常容易导致死锁,如果没有恰当地设计和同步生产者和消费者线程,可能会造成程序无法继续执行。因此,在使用 SynchronousQueue 时要注意线程同步和错误处理。

以下是一个 SynchronousQueue 可能导致死锁的示例情况:

public class SynchronousQueueDeadlockDemo {
    public static void main(String[] args) {
        final SynchronousQueue<Integer> queue = new SynchronousQueue<>();

        Thread thread1 = new Thread(() -> {
            try {
                // 线程1尝试将数据放入队列
                int data = 42;
                queue.put(data);
                System.out.println("线程1放入数据:" + data);

                // 接着,线程1尝试从队列中获取数据,但此时没有其他线程来获取
                int result = queue.take();
                System.out.println("线程1获取数据:" + result);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        Thread thread2 = new Thread(() -> {
            try {

                // 接着,线程2尝试将数据放入队列,但此时没有其他线程来获取
                int result = 100;
                queue.put(result);
                System.out.println("线程2放入数据:" + result);

                // 线程2尝试从队列中获取数据,但此时没有数据可用
                int data = queue.take();
                System.out.println("线程2获取数据:" + data);

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        thread1.start();
        thread2.start();
    }
}

可以看到线程1,线程2 都尝试向SynchronousQueue中放入元素,都阻塞在这里 。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值