2010-05-14 21 views
7

¿Por qué java.lang.Object tiene dos métodos de notificación: y notifyAll? Parece que notifyAll hace al menos todo lo que notify hace, entonces ¿por qué no solo usa notifyAll todo el tiempo? Si se usa notifyAll en lugar de notify, ¿el programa sigue siendo correcto y viceversa? ¿Qué influye en la elección entre estos dos métodos?Java: cuándo usar notify o notifyAll?

+0

La respuesta aceptada a esa pregunta insinúa una respuesta: que la diferencia es el rendimiento, que despierta hilos que no pueden hacer ningún trabajo real al usar notifyTodo es simplemente un problema de rendimiento. Así que creo que eso responde a esta pregunta: notificar que todo es siempre correcto, pero no tan eficiente. – mdma

+2

Desde Java 5 (en 2004), se ha agregado una nueva biblioteca de concurrencia. (Esta biblioteca es en realidad mucho más antigua) Sugiero que use esas clases y desaconsejaría el uso de notify o notifyAll. –

+0

La respuesta a esta pregunta está aquí en StackOverflow: [Java notify() vs. notifyAll()] (https://stackoverflow.com/questions/37026/java-notify-vs-notifyall-all-over-again) . – smountcastle

Respuesta

1

Según el Javadoc para notify:

Despierta un solo hilo que está esperando en el monitor de este objeto. Si hay hilos esperando en este objeto, uno de ellos se elige para ser despertado. La elección es arbitraria y ocurre a discreción de la implementación. Un hilo espera en el monitor de un objeto llamando a uno de los métodos de espera.

Esto podría ser útil si ha tenido una aplicación que utiliza, por ejemplo, una cola de incluir un producto y luego tiene muchos subprocesos de trabajo que va a extraer los objetos fuera de la cola. Cuando un artículo está listo, puede llamar al notify para despertar a un solo trabajador y procesar el artículo. Es cierto que este ejemplo es un poco artificial, probablemente haya mejores formas de implementar esto en Java, pero se entiende la idea.

1

Dos ejemplos típicos.

Digamos que tiene un hilo de productor y un hilo de consumidor. Cada "paquete" producido por el productor debe ser consumido por un consumidor. El consumidor pone algo en una cola y luego llama al notify() (Solo debe pasar un consumidor para procesar un "paquete").

Digamos que desea recibir una notificación cuando finaliza un largo proceso. Desea un pitido y una actualización de pantalla. El proceso realiza notifyAll() para notificar tanto el hilo de pitido como el hilo de actualización de pantalla.

0

La diferencia es que notify() golpea solo el hilo que espera en el hilo actual. Para la mayoría de las aplicaciones productor/consumidor y delegar y esperar, este es el método adecuado para usar. Además, si solo hay otro subproceso esperando en el subproceso actual, no hay necesidad de notificar más de ese subproceso en espera.

Por el contrario, notifyAll() thumps todos de los otros hilos esperando en el actual hilo. Esto es más útil en situaciones donde cada subproceso que duerme (relacionado) debe hacer algo, como en respuesta a un evento fatal o de gran importancia que el hilo notificador encierra.

1
//contribute By E.Thulasiram and Team 
    class AA extends Thread{ 
AA a; 
public void get(AA a){ 
    this.a=a; 
} 
public void run(){ 
    System.out.println("one"); 
    synchronized (a) { 
     try{ 
      a.wait(); 
      System.out.println("one wake up"); 
      this.wait(); 
     }catch(Exception e){ 
      System.out.println(e); 
     } 
    } 
} 
    } 
    class BB extends Thread{ 
AA a; 
public void get(AA a){ 
    this.a=a; 
} 
public void run(){ 
    System.out.println("two"); 
    synchronized (a) { 
     try{ 
      a.wait(); 
      System.out.println("two wake up"); 
     }catch(Exception e){ 
      System.out.println(e); 
     } 
    } 
} 
    } 
    class CC extends Thread{ 
AA a; 
public void get(AA a){ 
    this.a=a; 
} 
public void run(){ 
    synchronized (a) { 
     a.notifyAll(); 
     System.out.println("NotifyAll"); 
    } 
} 
    } 
    class DD{ 
public static void main(String args[]){ 
    AA a=new AA(); 
    BB b=new BB(); 
    CC c=new CC(); 
    a.get(a); 
    a.start(); 
    b.get(a); 
    b.start(); 
    c.get(a); 
    c.start(); 
} 
    } 
Cuestiones relacionadas