一、介绍:
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中放入元素,都阻塞在这里 。