2013-04-11 44 views
0

我有2個功能。第一個discoverHosts()向其他計算機發送請求消息。在此之後,它將通過await命令進入睡眠狀態。當他接收到響應時,單獨的威脅將調用handleMessage()函數。在處理響應之後,他使用notifyAll()讓discoderHosts()知道他必須檢查是否收到所有響應。爲什麼不等待線程激活signalAll?

DiscoverHosts()會在他調用該函數時等待。但是,當單獨的威脅調用handleMessage()時,當handleMessage調用signalAll()時,discoverHosts()不會喚醒。我調試debuggig,如果signalAll()被調用,並且是這種情況。我的項目中的其他地方几乎有相同的代碼,它可以工作。

你們中的任何人都知道我忽略了什麼?

private final Lock lock = new ReentrantLock(); 
private final Condition allReceived = lock.newCondition(); 

private void discoverHosts() throws Exception { 
    lock.lock(); 
    externalNodes = new HashMap<String, NodeAddress>(); 
    Message msg = new Message(null, "REQUEST_IP"); 
    logger.debug("Broadcasting ip request, waiting responses"); 
    channel.send(msg); 
    // TODO:Write a time-out 
    while (channel.getView().size() - 1 != externalNodes.keySet().size()) { 
     logger.debug("Channel: " + (channel.getView().size() - 1)); 
     logger.debug("Responses: "+ externalNodes.keySet().size()); 
     allReceived.await(); 
    } 
    logger.debug("All answers received"); 
    lock.unlock(); 
} 

protected void handleMessage(Message msg) { 
    lock.lock(); 
    if (!((String) msg.getObject()).matches("IP_RESPONSE:[0-9.]*")) 
     return; 
    logger.debug("Received answer from " + msg.getObject()); 
    String ip = ((String) msg.getObject()).replaceAll("IP_RESPONSE:", ""); 
    // externalHostIps.add(ip); 
    NodeAddress currentAddress = new NodeAddress(ip, msg.getSrc()); 
    externalNodes.put(ip, currentAddress); 
    logger.debug("Signalling all threads"); 
    allReceived.signalAll(); 
    lock.unlock(); 
    logger.debug("Unlocked"); 
} 

記錄儀輸出:

4372 [main] DEBUG [email protected] - Broadcasting ip request, waiting responses 
4372 [main] DEBUG [email protected] - Channel: 1 
4372 [main] DEBUG [email protected] - Responses: 0 
4394 [Incoming-1,webhackarena,leendert-K53SV-53745] DEBUG [email protected] - Received answer from IP_RESPONSE:192.168.1.106 
4396 [Incoming-1,webhackarena,leendert-K53SV-53745] DEBUG [email protected] - Signalling all threads 
4397 [Incoming-1,webhackarena,leendert-K53SV-53745] DEBUG [email protected] - Unlocked 
+0

' 「字符串」 +新的整數(N)的ToString()'是一樣的' 「串」 + N' – 2013-04-11 16:51:45

+0

@PeterLawrey不知道,完全解決了鎖定問題。哈。 – 2013-04-11 16:53:15

+2

你的日誌輸出是什麼?無論如何,你應該在try/finally Blocks中包裝'lock()'。 – 2013-04-11 16:53:39

回答

3

我覺得你的問題是此行

if (!((String) msg.getObject()).matches("IP_RESPONSE:[0-9.]*")) 
    return; 

你獲得鎖,從不釋放它的一些條件下,這意味着。

總是使用try...finally塊與Lock以避免此問題。

protected void handleMessage(Message msg) { 
    lock.lock(); 
    try { 
     if (!((String) msg.getObject()).matches("IP_RESPONSE:[0-9.]*")) 
      return; 
     logger.debug("Received answer from " + msg.getObject()); 
     String ip = ((String) msg.getObject()).replaceAll("IP_RESPONSE:", ""); 
     // externalHostIps.add(ip); 
     NodeAddress currentAddress = new NodeAddress(ip, msg.getSrc()); 
     externalNodes.put(ip, currentAddress); 
     logger.debug("Signalling all threads"); 
     allReceived.signalAll(); 
    } finally { 
     lock.unlock(); 
    } 
} 
+0

我假設他正在進行'signalAll()'方法調用。如果他假設他到達那裏,那麼你是正確的。 +1 – Gray 2013-04-11 17:02:25

+0

這個技巧很奇怪,因爲我調試並確認signalAll()被調用,而且我的日誌也證實了它。感謝Thanx的快速幫助。 – Dommicentl 2013-04-11 17:08:05

+0

@Vogabe你在'return'之前沒有日誌條目 - 你最有可能擁有多個消息處理程序。 – 2013-04-11 17:13:06

1

然而,當單獨的威脅電話的handleMessage(),discoverHosts()不清醒時的handleMessage調用signalAll()

我懷疑你有兩個不同類的問題,因爲Condition allReceivedprivate final,他們實際上並沒有處理相同的情況。

如果您嘗試調試此操作(或使用System.out.println調試),請確保您的包裝類的實例在兩個線程中都是相同的。