2013-04-11 69 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调试),请确保您的包装类的实例在两个线程中都是相同的。