2013-02-26 92 views
0

我遇到的問題是像單個生產者多個消費者問題。除了消費者是「不同的」,我需要一種「偷看」新產品的方式(以檢查它是誰)。從Java攔截之前檢查隊列

問題實際上是服務於多個客戶端線程的單個服務器線程。客戶端將請求信息,然後服務器應回覆此客戶端

我該怎麼做?一個可能性是一個循環,如:

while (true) { 
    if (q.peek() ... check here ...) { 
     // do something 
    } else { 
     Sleep(...); // prevent taking up too much CPU? 
    } 
} 

但似乎不理想/正確?

+2

消耗不是有偷看,如何建立不同隊列每種消息類型,因此您可以將相應的使用者與每個隊列相關聯。 – gerrytan 2013-02-26 04:05:21

+0

服務器線程是生產者,並且多個客戶端線程是多個消費者? – 2013-02-26 04:20:50

回答

2

這裏有兩種選擇:

選項1.有隊列的一個消費者認爲起飛物品和代表他們的「真實」的消費者。這將需要你做很多工作,因爲你的主要消費者將不得不知道哪些「真正的」消費者很忙。另外,如果其中一個「真實」消費者比其他消費者獲得更多資源,則它有可能在主消費者等待切換消息時阻止隊列。

更好的解決方案是:

選項2.使用一個隊列爲每種類型的消費者。您的製作人員將確定每個消息類型屬於哪個隊列並將其放入正確的隊列中。然後每個消費者將從其感興趣的隊列中拉出。

0

您可能需要通過在單個塊中同步它們來使以下操作成爲原子操作。

// Make sure queue is final. If not, use a final Object monitor. 
synchronized(queue) { 
    queue.peek 
    queue.pool 
} 

這是爲了確保你的後消費者線程發現隊列包含正確的有針對性的信息(通過BlockingQueue.peek),它可以使用該消息(通過BlockingQueue.pool

不過,您的解決方案是不理想的。您正在實施名爲busy pooling的技術,這會浪費大量CPU資源。您不會利用BlockingQueue.poolBlockingQueue.pool會讓您的消費者線程處於等待階段,直到數據可用。

要充分利用BlockingQueue.pool,每個消費者線程都應該擁有自己的隊列。因此,他們可以撥打pool,而無需執行繁忙的peek

0

也許這是最好不要使用BlockingQueue的根本:

public class Synchronizer { 
    Object obj; 

    synchronized void put(Object obj) throws InterruptedException { 
     this.obj = obj; 
     notifyAll(); 
     while(obj != null) { 
      wait(); 
     } 
    } 

    synchronized Object take() throws InterruptedException { 
     for(;;) { 
      wait(); 
      if (obj instanceof MyObject) { 
       notifyAll(); 
       Object tmp = obj; 
       obj = null; 
       return tmp; 
      } 
     } 
    } 
} 

雖然有可能是一個版本Synchronzer的,從一個BlockingQueue的

+0

爲什麼要自己滾?鑑於JRE提供了一個經過測試的版本,這似乎是一個非常糟糕的做法。 – Gray 2013-02-26 21:51:47