/*
 * un thread si blocca con wait() sull'oggetto di sincronizzazione
 * un altro lo sblocca con notify() sullo stesso oggetto
 *
 * notify() sblocca il thread in attesa su wait(),
 * che comunque aspetta che l'altro termini il suo blocco sincronizzato
 * prima di ripartire
 */

class Attesa implements Runnable {
	@Override
	public void run() {
		synchronized("abcd") {
			try {
				System.out.println("		inizio wait");
				"abcd".wait();
				System.out.println("		fine wait");
			}
			catch (InterruptedException e) {
			}
		}
	}
}

class Sblocca implements Runnable {
	@Override
	public void run() {
		synchronized("abcd") {
			try {
				System.out.println("inizio");
				Thread.sleep(2000);
				System.out.println("mando notify");
				"abcd".notify();
				System.out.println("inviato");
				System.out.println("attesa");
				Thread.sleep(2000);
				System.out.println("fine blocco sincronizzato");
			}
			catch (InterruptedException e) {
			}
		}
	}
}

public class Blocco {
	public static void main(String[] args) throws InterruptedException {
		Attesa a;
		Sblocca b;
		Thread ta, tb;

		a = new Attesa();
		ta = new Thread(a);
		b = new Sblocca();
		tb = new Thread(b);

		ta.start();
		tb.start();

		ta.join();
		tb.join();
	}
}
