2012-02-14 13 views
5

Esto es realmente extraño para mí, pero parece que notifyAll()/notify() falló en mi programa. El código es bastante complicado, básicamente tengo tres hilos A, B, CJava - notifyAll() y notify() ¿fallaron? ¿Es posible?

A envía la solicitud a B y espera() en la solicitud con un tiempo de espera de 10 segundos, cuando B finaliza, llama a notify() para despertar hasta A.

C en un deadloop alimenta muchas cadenas a A a través de una cola, A las recoge e imprime. Cada vez que A imprime una cadena, envía una solicitud a B y espera.

lo tanto, el flujo de trabajo viene a ser:

C mantiene la alimentación de una de deadloop

  1. Una imprime cadena de C
  2. A envía la solicitud a B y esperar (10)
  3. B notify() A ......

  4. A imprime una cadena de C .... una y otra vez ....

Esto funciona en los primeros segundos. sin embargo, después de un momento veo cuando B imprime que tiene notify() A, A todavía está esperando porque la cola que C usa para alimentar A se incrementa rápidamente, y no se imprime ninguna cadena por A. Finalmente, después de 10 segundos , A se queja del tiempo de espera de la solicitud.

Parece que notify() falló porque B imprimió un mensaje después de llamar a notify(). Teniendo en cuenta wait/notify es una característica radical de Java, no puedo creer que falle. ¿Es posible?

+8

Are you sure * A is "still waiting"? La otra posibilidad es que * comenzó * esperando * después de * la notificación, que sería código roto. (Nunca debe esperar por algo que ya ha sucedido.) –

+0

Quizás B haya llamado notificar ANTES de que las llamadas esperen –

+1

queremos código por favor. – vulkanino

Respuesta

2

notify() solo funcionará si hay un thread wait() en espera en ese momento.

La expresión idiomática que debe usar es cambiar un estado en el mismo bloque sincronizado que notify()/notifyAll(). En el bloque de espera, revisa repetidamente el cambio de estado. De esta forma, si la notificación se activó demasiado pronto, hay un cambio de estado para registrarla. Además, si la espera se despierta espuria, volverá a esperar si el estado no ha cambiado.

public synchronized void notifyReady() { 
    ready = true; 
    notifyAll(); 
} 

public synchronized void waitForReady() throws InterruptedException { 
    while(!ready) 
     wait(); 
} 
+0

Gracias chicos. El problema del tiempo ha demostrado ser causa –