2012-09-04 87 views
2

如果我們想實現資源池,比如數據庫連接池。你將使用哪個併發集合? BlockingQueueSemaphoreBlockingQueue vs Semaphore

對於BlockingQueue,就像生產者 - 消費者設計模式一樣,生產者將把所有連接放在隊列上,並且使用者將從隊列中取得下一個可用連接。

對於Semaphore,您指定池大小的信號量,並獲取許可證,直到您達到池大小並等待其中任何人釋放許可證並將該資源放回池中。

哪一個更簡單?以及我們只能使用一個而不是其他的情況?

+1

您不會在BlockingQueue上放置請求,您會將_connections_置於BlockingQueue中。 – jtahlborn

+0

你是對的,我要更新一下 – peter

回答

12

BlockingQueue更簡單,因爲它也會跟蹤連接/資源。

例如

public abstract class ResourcePool<Resource> { 
    private final BlockingQueue<Resource> free; 

    protected ResourcePool(int freeLimit) { 
     free = new ArrayBlockingQueue<>(freeLimit); 
    } 

    public Resource acquire() { 
     Resource resource = free.poll(); 
     return resource == null ? create() : resource; 
    } 

    public void recycle(Resource resource) { 
     if (!free.offer(resource)) 
      close(resource); 
    } 

    protected abstract Resource create(); 

    protected abstract void close(Resource resource); 
} 

正如您所看到的,BlockingQueue有助於跟蹤免費資源並確保沒有太多免費資源。它是線程安全的,無需顯式鎖定。

如果你使用一個信號量,你仍然需要的資源存儲在一個集合中(使信號冗餘;)

+1

的確很好 - 你如何獲得連接(當它們不再使用時)? – assylias

+1

@assylias我添加了一個例子。 –

0

許多阻塞隊列與信號量實現的,無論如何,(也許互斥/ futex的/ CS) 。我使用阻塞隊列進行對象存儲 - 一旦有阻塞隊列可用,爲什麼還要爲對象池使用其他任何東西?

0

對於高級連接池,我可能不會使用。正如@PeterLawrey指出的那樣,BlockingQueue對最初存在所有資源的簡單池最有意義。然而,如果你想做更復雜的事情,比如按需創建資源,那麼你很可能需要額外的併發結構。在這種情況下,最終可能最終會使用簡單的同步塊或Lock。