Diferencia entre notificar() y notificar a todos() en Java

Los métodos de notificación() y notificar a todos() con los métodos de espera() se utilizan para la comunicación entre los subprocesos. Un subproceso que entra en estado de espera al llamar al método wait() estará esperando el estado hasta que cualquier otro subproceso llame al método de notificación() o de notificación a todos() en el mismo objeto. 

notificar(): el método de notificación() se define en la clase de objeto, que es la clase de nivel superior de Java. Se usa para activar solo un subproceso que está esperando un objeto, y ese subproceso luego comienza a ejecutarse. El método de notificación de clase de subproceso() se utiliza para activar un solo subproceso.

notificarTodos(): El notificarTodos() activa todos los subprocesos que están esperando en el monitor de este objeto. Un subproceso espera en el monitor de un objeto llamando a uno de los métodos de espera. Los subprocesos activados no podrán continuar hasta que el subproceso actual renuncie al bloqueo de este objeto.

Ahora la pregunta es notificar() y notificar a todos() el método se usa para notificar al hilo en espera, luego cuál es la diferencia entre ellos o dónde debemos usar el método de notificación() y dónde debemos ir para notificar a todos() ¿método? 

No Señor. Llave notificar() notificar a todos() 
1 Notificaciones En el caso de multiThreading, el método de notificación() envía la notificación a solo un hilo entre los múltiples hilos en espera que están esperando el bloqueo de envío. Mientras que los métodos de applyAll() en el mismo contexto envían notificaciones a todos los subprocesos en espera en lugar de a un solo subproceso.
2 Identificaciones de hilos Como en el caso del método de notificación(), la notificación se envía a un solo hilo entre los múltiples hilos en espera, por lo que es seguro cuál de esos hilos en espera recibirá el bloqueo. Por otro lado, notificarTodos() envía una notificación a todos los subprocesos en espera. Por lo tanto, no está claro cuál de los subprocesos recibirá el bloqueo.
3 Factor de riesgo En el caso del método de notificación(), el riesgo de que falte un hilo es alto, ya que la notificación se envía solo a un hilo, y si se pierde, ningún otro hilo recibirá una notificación y, por lo tanto, el bloqueo. Mientras que en el caso de notificarTodos(), envía una notificación a todos los subprocesos en espera y, por lo tanto, si algún subproceso pierde la notificación, hay otros subprocesos para hacer el trabajo. Por lo tanto, el riesgo es menor.
4 Actuación El consumo de memoria y CPU es menor en el método de notificación() en comparación con el método de notificación() ya que la notificación se envía a un solo hilo, por lo que el rendimiento es mejor en comparación con el método de notificación(). Por otro lado, el costo de no notificar se reduce y la notificación se envía a todos los subprocesos en espera, el consumo de memoria y CPU es mayor en comparación con la notificación() y, por lo tanto, el rendimiento de la notificación() es menor.
5 Intercambiable En el caso del método de notificación(), solo hay un único subproceso en la imagen, por lo que no es posible ningún concepto de subproceso intercambiable. Si bien deberíamos optar por notificar a Todos() si todos sus subprocesos en espera son intercambiables (no importa el orden en que se activan).

Entendamos cómo se comporta el método de notificación():

Java

// Java program to illustrate the
// behaviour of notify() method
class Geek1 extends Thread {
    public void run()
    {
        synchronized (this)
        {
            System.out.println(
                Thread.currentThread().getName()
                + "...starts");
            try {
                this.wait();
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(
                Thread.currentThread().getName()
                + "...notified");
        }
    }
}
class Geek2 extends Thread {
    Geek1 geeks1;
    
    Geek2(Geek1 geeks1){ 
      this.geeks1 = geeks1; 
    }
    
    public void run()
    {
        synchronized (this.geeks1)
        {
            System.out.println(
                Thread.currentThread().getName()
                + "...starts");
  
            try {
                this.geeks1.wait();
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(
                Thread.currentThread().getName()
                + "...notified");
        }
    }
}
class Geek3 extends Thread {
    Geek1 geeks1;
    Geek3(Geek1 geeks1) { this.geeks1 = geeks1; }
    public void run()
    {
        synchronized (this.geeks1)
        {
            System.out.println(
                Thread.currentThread().getName()
                + "...starts");
            this.geeks1.notify();
            System.out.println(
                Thread.currentThread().getName()
                + "...notified");
        }
    }
}
class MainClass {
    public static void main(String[] args)
        throws InterruptedException
    {
  
        Geek1 geeks1 = new Geek1();
        Geek2 geeks2 = new Geek2(geeks1);
        Geek3 geeks3 = new Geek3(geeks1);
        Thread t1 = new Thread(geeks1, "Thread-1");
        Thread t2 = new Thread(geeks2, "Thread-2");
        Thread t3 = new Thread(geeks3, "Thread-3");
        t1.start();
        t2.start();
        Thread.sleep(100);
        t3.start();
    }
}

Producción: 

Thread-1...start
Thread-2...starts
Thread-3...starts
Thread-3...notified
Thread-1...notified

Entendamos cómo se comporta el método notificarTodos():  

Java

// Java program to illustrate the
// behavior of notifyAll() method
  
class Geek1 extends Thread {
    public void run()
    {
        synchronized (this)
        {
            System.out.println(
                Thread.currentThread().getName()
                + "...starts");
            try {
                this.wait();
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(
                Thread.currentThread().getName()
                + "...notified");
        }
    }
}
class Geek2 extends Thread {
    Geek1 geeks1;
    
    Geek2(Geek1 geeks1){ 
      this.geeks1 = geeks1; 
    }
    
    public void run()
    {
        synchronized (this.geeks1)
        {
            System.out.println(
                Thread.currentThread().getName()
                + "...starts");
  
            try {
                this.geeks1.wait();
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(
                Thread.currentThread().getName()
                + "...notified");
        }
    }
}
class Geek3 extends Thread {
    Geek1 geeks1;
    Geek3(Geek1 geeks1) { this.geeks1 = geeks1; }
    public void run()
    {
        synchronized (this.geeks1)
        {
            System.out.println(
                Thread.currentThread().getName()
                + "...starts");
  
            this.geeks1.notifyAll();
            System.out.println(
                Thread.currentThread().getName()
                + "...notified");
        }
    }
}
class MainClass {
    public static void main(String[] args)
        throws InterruptedException
    {
  
        Geek1 geeks1 = new Geek1();
        Geek2 geeks2 = new Geek2(geeks1);
        Geek3 geeks3 = new Geek3(geeks1);
        Thread t1 = new Thread(geeks1, "Thread-1");
        Thread t2 = new Thread(geeks2, "Thread-2");
        Thread t3 = new Thread(geeks3, "Thread-3");
        t1.start();
        t2.start();
        Thread.sleep(100);
        t3.start();
    }
}
Producción

Thread-1...starts
Thread-2...starts
Thread-3...starts
Thread-3...notified
Thread-1...notified
Thread-2...notified

¿Cuándo usar el método de notificación() y notificar a todos()?

  • En el caso del bloqueo mutuamente excluyente, solo uno de los subprocesos en espera puede hacer algo útil después de recibir la notificación (en este caso, adquirir el bloqueo). En tal caso, preferiría usar notificar(). Si se implementa correctamente, también podría usar notificar a todos() en esta situación, pero despertaría innecesariamente subprocesos que de todos modos no pueden hacer nada.
  • En algunos casos, todos los subprocesos en espera pueden tomar medidas útiles una vez que finaliza la espera. Un ejemplo sería un conjunto de subprocesos que esperan que finalice una determinada tarea; una vez finalizada la tarea, todos los subprocesos en espera pueden continuar con sus asuntos. En tal caso, usaría notificarTodos() para activar todos los subprocesos en espera al mismo tiempo.

Aplicaciones de notificar() y notificarTodos()

  • Una operación de mantenimiento en un recurso compartido, donde varios subprocesos esperan que se complete la operación antes de acceder al recurso; para estos, debemos optar por notificar a Todos().
  • Digamos que tenemos un hilo productor y un hilo consumidor. Cada “paquete” producido por el productor debe ser consumido por un consumidor. El consumidor pone algo en una cola y luego llama a notificar().
  • Queremos recibir una notificación cuando finalice un proceso largo. Quiere un pitido y una actualización de pantalla. El proceso realiza la notificación a todos() para notificar tanto el subproceso de pitido como el subproceso de actualización de pantalla.

Este artículo es una contribución de Bishal Kumar Dubey . Si le gusta GeeksforGeeks y le gustaría contribuir, también puede escribir un artículo usando contribuya.geeksforgeeks.org o envíe su artículo por correo a contribuya@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks. Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *