2013-04-11 1 views
0

У меня есть 2 функции. Первое обнаружениеHosts() отправляет сообщение с запросом на другие компьютеры. После этого он засыпает с командой ожидания. Отдельная угроза вызывает функцию handleMessage(), когда он получает ответ. После того, как он обработает ответ, он использует notifyAll(), чтобы discoderHosts() знал, что он должен проверить, что все ответы получены.Почему не ожидающий поток, активированный сигналом All?

DiscoverHosts() действительно ждет, когда он вызывает функцию. Однако, когда отдельная угроза вызывает handleMessage(), функция DiscoverHosts() не пробуждается, когда handleMessage вызывает signalAll(). Я проверил при 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"); 
} 

Logger:

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

' "строка" + новое Целое число (п) .ToString()' так же, как ' "строка" + N' –

+0

@PeterLawrey не уверен, что полностью решает проблему блокировки. Ха. –

+2

Каков ваш выход в журнал? В любом случае вы должны обернуть 'lock()' в try/finally Blocks. –

ответ

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

+0

Это сделало трюк, странно, потому что я отлаживал и подтверждал, что был вызван signalAll(), а также мои журналы подтверждают это. Thanx для быстрой помощи. – Dommicentl

+0

@ Vogabe у вас нет записи журнала перед 'return' - вы, скорее всего, имеете более одного обработчика сообщений. –

1

Однако, когда отдельная угроза вызывает handleMessage(), discoverHosts() не просыпаются, когда handleMessage называет signalAll()

Я подозреваю, что у вас есть два разных экземпляра класса, о которых идет речь, и поскольку Condition allReceived - private final, они не имеют дело с одним и тем же условием.

Если вы пытаетесь отладить это (или используете отладку System.out.println), убедитесь, что ваш экземпляр класса упаковки одинаковый в обоих потоках.