1. 程式人生 > >SynchronousQueue和LinkedBlockingQueue區別

SynchronousQueue和LinkedBlockingQueue區別

在多執行緒開發中,會用到SynchronousQueue(new CachedThreadPool())和LinkedBlockingQueue(new FixedThreadPoll())

我們來簡單分析一下這兩個佇列的區別

SynchronousQueue:

  offer():當執行緒offer操作時,當same mode時,加入佇列失敗,即時返回 (如果是put操作,元素會儲存到佇列中,並且阻塞等待);

當complimentary mode時,立即把元素transfer給等待的take執行緒

        take():執行緒take操作,當same mode時,該執行緒把元素儲存到佇列中,並且阻塞等待(如果是poll操作,元素會加入佇列失敗,即時返回);

當complimentary mode時,立即在佇列中找到等待的put執行緒關聯的元素,取出來,返回

 

LinkedBlockingQueue

  offer(): 執行緒把元素放入佇列中(多執行緒併發競爭),返回,超過bound,返回失敗

 1 /** Lock held by take, poll, etc */
 2     private final ReentrantLock takeLock = new ReentrantLock();
 3 
 4     /** Wait queue for waiting takes */
 5     private
final Condition notEmpty = takeLock.newCondition(); 6 7 /** Lock held by put, offer, etc */ 8 private final ReentrantLock putLock = new ReentrantLock(); 9 10 /** Wait queue for waiting puts */ 11 private final Condition notFull = putLock.newCondition(); 12 13 14 public boolean offer(E e) {
15 if (e == null) throw new NullPointerException(); 16 final AtomicInteger count = this.count; 17 if (count.get() == capacity) 18 return false; 19 int c = -1; 20 Node<E> node = new Node<E>(e); 21 final ReentrantLock putLock = this.putLock; 22 putLock.lock(); 23 try { 24 if (count.get() < capacity) { 25 enqueue(node); 26 c = count.getAndIncrement(); 27 if (c + 1 < capacity) 28 notFull.signal(); 29 } 30 } finally { 31 putLock.unlock(); 32 } 33 if (c == 0) 34 signalNotEmpty(); 35 return c >= 0; 36 }
offer方法

 

       take(); 佇列不為空時,獲取元素(多執行緒併發競爭),為空時,阻塞等待

 1 public E take() throws InterruptedException {
 2         E x;
 3         int c = -1;
 4         final AtomicInteger count = this.count;
 5         final ReentrantLock takeLock = this.takeLock;
 6         takeLock.lockInterruptibly();
 7         try {
 8             while (count.get() == 0) {
 9                 notEmpty.await();
10             }
11             x = dequeue();
12             c = count.getAndDecrement();
13             if (c > 1)
14                 notEmpty.signal();
15         } finally {
16             takeLock.unlock();
17         }
18         if (c == capacity)
19             signalNotFull();
20         return x;
21     }
View Code

 

設想一種場景:

  當有大量執行緒在offer和take時,

  1、LinkedBlockingQueue在入隊和出隊時,併發競爭激烈,cpu執行緒切換頻繁,效能較低;

   2、SynchronousQueue中每一個元素對應一個put執行緒、一個take執行緒,不會存在鎖競爭

  但是反過來 SynchronousQueue需要的執行緒數較多,如果take消費不及時,會導致put執行緒阻塞(如果是使用offer的話,會加入佇列失敗)