Categorías
Concurrency

Java Thread: ejemplos denotificar () y esperar ()

Este artículo contiene dos ejemplos de código para demostrar la simultaneidad de Java. Representan un uso muy típico. Al comprenderlos, comprenderá mejor las notificaciones () y la espera ().

1. Algunos conocimientos previos

  1. synchronized La palabra clave se utiliza para acceso exclusivo.
  2. Para sincronizar un método, simplemente agregue la palabra clave sincronizada a su declaración. Entonces no se pueden intercalar dos invocaciones de métodos sincronizados en el mismo objeto.
  3. Las declaraciones sincronizadas deben especificar el objeto que proporciona el bloqueo intrínseco. Cuando se utiliza sincronizado (esto), debe evitar sincronizar las invocaciones de los métodos de otros objetos.
  4. wait() le dice al hilo de llamada que abandone el monitor y se vaya a dormir hasta que otro hilo entre en el mismo monitor y llame anotificar ().
  5. notify() despierta el primer hilo que llamó wait() en el mismo objeto.

2. notificar () y esperar () – ejemplo 1

public class ThreadA {
    public static void main(String[] args){
        ThreadB b = new ThreadB();
        b.start();
 
        synchronized(b){
            try{
                System.out.println("Waiting for b to complete...");
                b.wait();
            }catch(InterruptedException e){
                e.printStackTrace();
            }
 
            System.out.println("Total is: " + b.total);
        }
    }
}
 
class ThreadB extends Thread{
    int total;
    @Override
    public void run(){
        synchronized(this){
            for(int i=0; i<100 ; i++){
                total += i;
            }
            notify();
        }
    }
}
  Monitores: la idea básica de la sincronización de Java

En el ejemplo anterior, un objeto, b, está sincronizado. b completa el cálculo antes de que el hilo principal emita su valor total.

Producción:

Waiting for b to complete...
Total is: 4950

Si b no está sincronizado como el siguiente código:

public class ThreadA {
	public static void main(String[] args) {
		ThreadB b = new ThreadB();
		b.start();
 
		System.out.println("Total is: " + b.total);
 
	}
}
 
class ThreadB extends Thread {
	int total;
 
	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			total += i;
		}
	}
}

El resultado sería 0, 10, etc. Porque la suma no se termina antes de usarse.

3. notificar () y esperar () – ejemplo 2

El segundo ejemplo es más complejo, vea los comentarios.

import java.util.Vector;
 
class Producer extends Thread {
 
    static final int MAXQUEUE = 5;
    private Vector messages = new Vector();
 
    @Override
    public void run() {
        try {
            while (true) {
                putMessage();
                //sleep(5000);
            }
        } catch (InterruptedException e) {
        }
    }
 
    private synchronized void putMessage() throws InterruptedException {
        while (messages.size() == MAXQUEUE) {
            wait();
        }
        messages.addElement(new java.util.Date().toString());
        System.out.println("put message");
        notify();
        //Later, when the necessary event happens, the thread that is running it calls notify() from a block synchronized on the same object.
    }
 
    // Called by Consumer
    public synchronized String getMessage() throws InterruptedException {
        notify();
        while (messages.size() == 0) {
            wait();//By executing wait() from a synchronized block, a thread gives up its hold on the lock and goes to sleep.
        }
        String message = (String) messages.firstElement();
        messages.removeElement(message);
        return message;
    }
}
 
class Consumer extends Thread {
 
    Producer producer;
 
    Consumer(Producer p) {
        producer = p;
    }
 
    @Override
    public void run() {
        try {
            while (true) {
                String message = producer.getMessage();
                System.out.println("Got message: " + message);
                //sleep(200);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
 
    public static void main(String args[]) {
        Producer producer = new Producer();
        producer.start();
        new Consumer(producer).start();
    }
}
  Java Thread: un código de ejemplo primordial

Una posible secuencia de salida:

Got message: Fri Dec 02 21:37:21 EST 2011
put message
put message
put message
put message
put message
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
put message
put message
put message
put message
put message
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011

Por Programación.Click

Más de 20 años programando en diferentes lenguajes de programación. Apasionado del code clean y el terminar lo que se empieza. ¿Programamos de verdad?

Deja una respuesta

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