【并发编程篇】同步队列SynchronousQueue


在这里插入图片描述

🍔简述同步队列

同步队列(Synchronous Queue)是一种特殊的队列数据结构,它具有以下特点:

  • 队列容量为0:同步队列的容量为0,即不能存储任何元素。它主要用于线程间的数据传输,而不是作为一个临时数据存储的结构。
  • 阻塞操作:同步队列的插入和删除操作都是阻塞的。当一个线程试图插入元素到同步队列时,如果队列已满,线程将被阻塞直到有其他线程从队列中删除元素;当一个线程试图从同步队列中删除元素时,如果队列为空,线程将被阻塞直到有其他线程向队列中插入元素。
  • 线程间的同步:同步队列提供了一种简单而有效的线程间通信方式。它可以用于线程之间传递数据、进行任务调度等场景。

同步队列的实现可以基于不同的同步原语,例如互斥锁、条件变量等。Java并发包中的SynchronousQueue就是一种常见的同步队列实现。

使用同步队列可以有效地实现线程间的同步和协作,避免了显式的锁和条件变量的使用,简化了代码的编写和维护。但需要注意合理使用同步队列,避免出现死锁和线程饥饿等问题。

总结起来,同步队列是一种阻塞的、容量为0的队列数据结构,用于实现线程间的同步和协作。

🌹代码实现

package org.Test6;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;

public class SynchronousQueueDemo {
    public static void main(String[] args) {
        BlockingQueue<String> blockingQueue = new SynchronousQueue<>(); //同步队列

        new Thread(()->{
            try {
                System.out.println(Thread.currentThread().getName()+" put 1");
                blockingQueue.put("1");
                System.out.println(Thread.currentThread().getName()+" put 2");
                blockingQueue.put("2");
                System.out.println(Thread.currentThread().getName()+" put 3");
                blockingQueue.put("3");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        },"T1").start();

        new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName()+"=>"+blockingQueue.take());
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName()+"=>"+blockingQueue.take());
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName()+"=>"+blockingQueue.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"T2").start();

    }
}

在这里插入图片描述

🛸代码讲解

SynchronousQueue 允许执行插入操作和删除操作的线程相互等待,因此该队列的容量为 0,即不能存储任何元素。在调用 put 方法时,如果队列中已经存在一个未被取走的元素,那么 put 操作将会阻塞直到该元素被取走,也就是说 SynchronousQueue 的 put 方法会阻塞当前线程直到另一个线程取出元素,而 take 方法也同样如此。因此,对于上述代码,在 T1 线程中调用 put 方法时,若前一个元素还未被取出,那么会被阻塞等待,所以只能往里面放一个元素,其他两个 put 操作都会被阻塞。在 T2 线程中调用 take 方法时,如果队列中没有元素,那么线程将被阻塞直到有另一个线程插入一个元素。因此,这段代码应该只输出 Thread-1 put 1 和 T2 => 1,其他的操作都会被阻塞等待。

在技术的道路上,我们不断探索、不断前行,不断面对挑战、不断突破自我。科技的发展改变着世界,而我们作为技术人员,也在这个过程中书写着自己的篇章。让我们携手并进,共同努力,开创美好的未来!愿我们在科技的征途上不断奋进,创造出更加美好、更加智能的明天!

在这里插入图片描述