2012-03-06 60 views
12

我有多個BlockingQueue包含要發送的消息。消費者可能少於隊列嗎?我不想循環隊列並繼續輪詢它們(忙等待),我不希望每個隊列都有一個線程。相反,我希望有一個線程在任何隊列上有消息可用時喚醒。多個阻塞隊列,單個使用者

+5

這和給多個生產者的單個阻塞隊列有什麼區別? – 2012-03-06 16:57:33

+0

我認爲Alex想要完成的是在多個阻塞隊列之上創建一個阻塞隊列(封裝),這樣一個消費者可以簡單地等待一個阻塞隊列。也許這種情況阻止了Alex要求生產者使用相同的阻塞隊列實例。 – sjlee 2012-03-06 17:25:36

+1

問題是我不希望每個隊列有多個消費者。如果我將它全部放在一個隊列中,消費者可以從同一隊列中吃東西。 所以,如果我有一個隊列與A和隊列與B的。只要還有另外一個B被採取,就不會採取B. – Alex 2012-03-07 22:28:58

回答

6

你可以做的一個技巧是擁有一個隊列隊列。所以你要做的是擁有一個所有線程訂閱的阻塞隊列。然後,當您將某些東西排入您的BlockingQueue中時,您還會將此阻止隊列排入此單個隊列。所以,你會碰到這樣的:

BlockingQueue<WorkItem> producers[] = new BlockingQueue<WorkItem>[NUM_PRODUCERS]; 
BlockingQueue<BlockingQueue<WorkItem>> producerProducer = new BlockingQueue<BlockingQueue<WorkItem>>(); 

然後,當你得到一個新的工作項目:

void addWorkItem(int queueIndex, WorkItem workItem) { 
    assert queueIndex >= 0 && queueIndex < NUM_PRODUCERS : "Pick a valid number"; 
    //Note: You may want to make the two operations a single atomic operation 
    producers[queueIndex].add(workItem); 
    producerProducer.add(producers[queueIndex]); 
} 

現在你的消費者可以在producerProducer所有塊。我不確定這個策略有多麼有價值,但它確實實現了你想要的。

+0

簡單而有效!謝謝! – Alex 2012-03-16 11:09:42

+0

@亞歷克斯:沒問題 - 我很好奇它是如何運作的。 – mindvirus 2012-03-16 12:23:58

4

LinkedBlockingMultiQueue做你要求的。它不允許消費者阻塞任意BlockingQueue,但可以從單個「多隊列」創建「子隊列」並獲得相同的效果。生產者在子隊列中提供,消費者可以阻止自己輪詢單個多隊列,等待任何元素。

它還支持優先級,即在考慮其他隊列之前從某些隊列中獲取元素。

例子:

LinkedBlockingMultiQueue<Int, String> q = new LinkedBlockingMultiQueue<>(); 
q.addSubQueue(1 /* key */, 10 /* priority */); 
q.addSubQueue(2 /* key */, 10 /* priority */); 
LinkedBlockingMultiQueue<Int, String>.SubQueue sq1 = q.getSubQueue(1); 
LinkedBlockingMultiQueue<Int, String>.SubQueue sq2 = q.getSubQueue(2); 

然後你就可以提供與調查:

sq1.offer("x1"); 
q.poll(); // "x1" 
sq2.offer("x2"); 
q.poll(); // "x2" 

免責聲明:我是庫的作者。