简介
SynchronousQueue实现BlockingQueue接口,是没有容量,无缓冲等待,并且内部不存储元素的阻塞队列,里面只能存在最多一个元素,也就是说:SynchronousQueue类的put/offer操作,必须等待take/poll操作唤醒,take操作必须put操作唤醒,没有take操作,多个put操作都堵塞,等待一个一个take操作来一个一个唤醒,同理,take操作也一样,生产者线程和消费者线程一定按照严格的交替顺序执行。
与其说SynchronousQueue是队列,其实它更像是只存放一个元素的点,内部没有数据的存储空间,队列不能peek,因为不存在元素,任何入队的线程都会阻塞,直到有线程来出队,也就是这个队列是一组操作,入队和出队要一起离开,出队也是一样,必须等入队,必须结伴而行;队列支持公平和非公平的模式(指的是队列匹配线程的顺序),公平模式的数据结构是队列(FIFO),非公平模式使用的是栈(LIFO)。
SynchronousQueue阻塞队列 在java.util.concurrent包 实现主要用于生产者-使用者队列,内部采用的是ArrayBlockingQueue阻塞原语,所以在功能上和ArrayBlockingQueue等同,但是它的优势在于它是轻量级的阻塞。
代码模拟
场景:分别创建消费者和生产者线程。生产者线程里面要放置三个元素,消费者线程要移除三个元素。
代码逻辑:生产者put生产三个元素,中间不调用如sleep、wait等同步方法,消费者take三个元素,每个take间隔3秒钟执行。不加同步之前,生产者会一次性生产三个元素,不会阻塞。
结果:生产者的三个元素不会同时放置进去,必须等待消费者来移除一个元素,再放置下一个元素
import java.util.concurrent.SynchronousQueue;
public class SynchronousQueueDemo {
public static void main(String[] args) {
SynchronousQueue<String> blockingQueue = new SynchronousQueue<>();
// 将会放置三个元素的生产者线程,无需在代码中显示调用同步方法
new Thread(() -> {
try{
System.out.println(Thread.currentThread().getName() + " 生产了元素A");
blockingQueue.put("A");
System.out.println(Thread.currentThread().getName() + " 生产了元素B");
blockingQueue.put("B");
System.out.println(Thread.currentThread().getName() + " 生产了元素C");
blockingQueue.put("C");
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "生产者").start();
// 将会消费三个元素的消费者线程,没有在代码中显示调用同步方法
// 每个消费操作等待3秒钟,此时put操作会跟着等待休眠3秒钟,直至take操作执行
new Thread(() -> {
try {
try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println(Thread.currentThread().getName() + " 消费了元素" + blockingQueue.take().toString());
try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println(Thread.currentThread().getName() + " 消费了元素" + blockingQueue.take());
try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println(Thread.currentThread().getName() + " 消费了元素" + blockingQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "消费者").start();
}
}