天天看點

java并發程式設計工具類JUC第六篇:SynchronousQueue同步隊列

java并發程式設計工具類JUC第六篇:SynchronousQueue同步隊列

在之前的文章中已經為大家介紹了java并發程式設計的工具:BlockingQueue接口、ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue、PriorityBlockingQueue,本文為系列文章第六篇。

本篇文章将為大家介紹并發程式設計集合類SynchronousQueue,它是BlockingQueue接口的實作類。與所有的BlockingQueue接口實作類不同的是:SynchronousQueue隊列的容量永遠是0(或者可以了解為容量為1的隊列,但是說隊列容量為1并不準确),這是因為SynchronousQueue實際上它不是一個真正的隊列,因為它不會為隊列中元素維護存儲空間,它隻是多個線程之間資料交換的媒介。

  • SynchronousQueue隊列的一個線程的插入動作總是會等待另一個線程的移除操作,反之亦然。
  • put()方法放入元素對象到 SynchronousQueue不會傳回結果(處于阻塞狀态),直到另一個線程執行take()移除元素對象.
  • peek()方法在BlockingQueue接口實作類中可以擷取元素,但不從隊列中移除該元素。但在SynchronousQueue隊列中該方法不可用。

SynchronousQueue 同步隊列例子

下面我們寫一個例子,來幫助我們了解SynchronousQueue的特性及用法。 SynchronousQueueProducer.java 啟動線程每隔一秒向隊列中放入一個Integer對象。

public class SynchronousQueueProducer implements Runnable {

   protected BlockingQueue<Integer> blockingQueue;
   public SynchronousQueueProducer(BlockingQueue<Integer> queue) {
      this.blockingQueue = queue;
   }

   [@Override](https://my.oschina.net/u/1162528)
   public void run() {
      int i = 0;
      while (true) {
         System.out.println(Thread.currentThread().getName() + " Put: " + ++i);
         try {
            blockingQueue.put(i);
            Thread.sleep(1000);  //每隔一秒生産一次
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }

}      

SynchronousQueueConsumer.java啟動線程每5秒從隊列中取出一個元素對象。

public class SynchronousQueueConsumer implements Runnable {
   protected BlockingQueue<Integer> blockingQueue;

   public SynchronousQueueConsumer(BlockingQueue<Integer> queue) {
      this.blockingQueue = queue;
   }

   [@Override](https://my.oschina.net/u/1162528)
   public void run() {
      while (true) {
         try {
            Integer data = blockingQueue.take();
            System.out.println(Thread.currentThread().getName() + " take(): " + data);
            Thread.sleep(5000);  //每隔5秒消費一次
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }

}      

SynchronousQueueExample.java 建立一個SynchronousQueue同步隊列,啟動一個生産者線程插入對象,兩個消費者線程移除對象。進行測試,看看效果。

public class SynchronousQueueExample {
    public static void main(String[] args) {
      final BlockingQueue<Integer> synchronousQueue = new SynchronousQueue<>();
    
      SynchronousQueueProducer queueProducer = new SynchronousQueueProducer(synchronousQueue);
      new Thread(queueProducer).start();
    
      SynchronousQueueConsumer queueConsumer1 = new SynchronousQueueConsumer(synchronousQueue);
      new Thread(queueConsumer1).start();
    
      SynchronousQueueConsumer queueConsumer2 = new SynchronousQueueConsumer(synchronousQueue);
      new Thread(queueConsumer2).start();
    }
}      
Thread-0 Put: 1
Thread-1 take(): 1
Thread-0 Put: 2
Thread-2 take(): 2
Thread-0 Put: 3
Thread-1 take(): 3
Thread-0 Put: 4
Thread-2 take(): 4
Thread-0 Put: 5
Thread-1 take(): 5
Thread-0 Put: 6
Thread-2 take(): 6
Thread-0 Put: 7
Thread-1 take(): 7
Thread-0 Put: 8
Thread-2 take(): 8
Thread-0 Put: 9
Thread-1 take(): 9
Thread-0 Put: 10
Thread-2 take(): 10
Thread-0 Put: 11
Thread-1 take(): 11
Thread-0 Put: 12
Thread-2 take(): 12      

繼續閱讀