Pure Java – 92 Thread – 09 – Thread Interaction

Merhaba Arkadaslar,
Bu bolumde java.lang.Object sinifinda yer alan wait , notify ve notifyAll metotlarini inceleyecegiz.

Bir thread mail-delivery threadi , diger threa ise mail-processor threadi olarak dusunelim.
wait-notify mekanizmasi yardimi ile, mail-processor threadi maili ornegin 2 saniyede bir surekli check edebilir ya da bunun yerine mail geldiginde beni uyar/bilgilendir diyebilir(notify).

Bir baska degisle , wait notify mekanizmasi , threadi bir nevi bekleme odasina alir ve diger threadin bilgilendirmesi/ilani ile(notify) bekleme odasindan cikmasini saglar.

wait , notify ve notifyAll metotlari mutlaka synchronized metot veya block icerisinden cagrilmalidir. Bir thread ilgili objenin kilidini ele gecirmeden wait ya da notify metotlarini cagiramaz.

wait ve notify olmadan bir ornek yapalim;

public class WithoutWaitNotifyTest {

	public static void main(String[] args) {
		Calculate calculateThread = new Calculate();
		calculateThread.start();

		System.out.println("After calculate...");
		System.out.println("total is: " + calculateThread.total);
		System.out.println("counter is: " + calculateThread.counter);

	}
}

class Calculate extends Thread {
	int total;
	int counter;

	@Override
	public void run() {

		for (int i = 0; i < 100000; i++) {
			total += i;
			counter = i;
		}

	}
}

Calculate sinifinda , dongu icerisinde basit bir islem yaptiriyoruz , ornegi bir kac kere calistirirsak farkli ciktilar elde ederiz, ornegin ;

After calculate…
total is: 0
counter is: 0

After calculate…
total is: 81836821
counter is: 14062

After calculate…
total is: 557997121
counter is: 38800

Burada amacimiz bu toplama islemi bittikten sonra yazdirmak , bu durumda wait notify mekanizmasini su sekilde kullanabiliriz.

public class WithWaitNotifyTest {

	public static void main(String[] args) {
		Calculate calculateThread = new Calculate();
		calculateThread.start();

		synchronized (calculateThread) {
			try {
				System.out.println("Waiting for calculateThread to complete...");
				calculateThread.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

			System.out.println("total is: " + calculateThread.total);
			System.out.println("counter is: " + calculateThread.counter);
		}

	}
}

class Calculate extends Thread {
	int total;
	int counter;

	@Override
	public void run() {
		synchronized (this) {
			for (int i = 0; i < 100000; i++) {
				total += i;
				counter = i;
			}
			notify();
		}
	}
}

calculateThread i start metodu ile calistirdikdan sonra , islemini tamamlamasini bekliyoruz. Bunun icin Calculate objesi uzerinden (calculateThrea referans degiskeni) synchronized kod blogu yaziyoruz. wait metodunu calculateThread referans degiskeni uzerinden cagiriyoruz boylelikle bu thread sonlana kadar diger threadlerin calismasini engelliyoruz.(block)

synchronized (calculateThread) {
			try {
				System.out.println("Waiting for calculateThread to complete...");
				calculateThread.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

			System.out.println("total is: " + calculateThread.total);
			System.out.println("counter is: " + calculateThread.counter);
		}

notify metodunu cagirarak , isimizin bittigini bildiriyoruz(notification) . Boylelikle blockladigimiz thread(main threadi) tekrar calismaya devam ediyor.

calculateThread bitene kadar main threadi blocklandigi icin ornegimizi calistirirsak her defasinda ayni ciktiyi elde ederiz.

Waiting for calculateThread to complete…
total is: 704982704
counter is: 99999

notifyAll metodu , tum bekleyen threadler icin bildirim yapacaktir(notification).
Tum threadler uyarilacak ve WAITING durumunda olan threadler RUNNABLE duruma gececektir.

class Message {

	private String text;

	public Message(String text) {
		this.text = text;
	}

	public String getText() {
		return text;
	}

	public void setText(String text) {
		this.text = text;
	}

}

class Waiter implements Runnable {

	Message message;

	public Waiter(Message message) {
		this.message = message;
	}

	@Override
	public void run() {
		synchronized (message) {
			try {
				System.out.println("Waiter is waiting for the notifier at " + Thread.currentThread().getName());
				message.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("Waiter is done waiting at : " + Thread.currentThread().getName());
		System.out.println("Waiter got the message:  " + message.getText());
	}

}

class Notifier implements Runnable {

	Message message;

	public Notifier(Message message) {
		this.message = message;
	}

	@Override
	public void run() {
		System.out.println("Notifier is sleeping for 3 seconds at ");
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		synchronized (message) {
			message.setText("Notifier took a nap for 3 seconds");
			System.out.println("Notifier is notifying waiting thread to wake up at ");
			message.notifyAll();
		}

	}

}

public class WaitNotifyExample {

	public static void main(String[] args) {

		Message message = new Message("Hello  notify test");

		Waiter waiter = new Waiter(message);
		Thread waiterThread = new Thread(waiter, "waiterThread");
		waiterThread.start();

		Thread waiterThread2 = new Thread(waiter, "waiterThread2");
		waiterThread2.start();

		Thread waiterThread3 = new Thread(waiter, "waiterThread3");
		waiterThread3.start();

		Notifier notifier = new Notifier(message);
		Thread notifierThread = new Thread(notifier, "notifierThread");
		notifierThread.start();

	}

}

Buradada 3 tane Waiter Threadi olusturduk , 1 tane Notifier Threadi olusturduk. Message sinifi tipindeki objemizi synchronized blogunda kilit olarak kullandik.  3 tane Thread’i beklemeye aldik/block.  Notifier sinifinin isi bittiginde Message objesinin kilidini bekleyen bu 3 Thread’e bildirim yaptik.

Waiter is waiting for the notifier at waiterThread
Waiter is waiting for the notifier at waiterThread2
Waiter is waiting for the notifier at waiterThread3
Notifier is sleeping for 3 seconds at
Notifier is notifying waiting thread to wake up at
Waiter is done waiting at : waiterThread3
Waiter is done waiting at : waiterThread2
Waiter is done waiting at : waiterThread
Waiter got the message: Notifier took a nap for 3 seconds
Waiter got the message: Notifier took a nap for 3 seconds
Waiter got the message: Notifier took a nap for 3 seconds

Burada notifyAll metodu yerine notify metodu kullanirsak ,  bu 3 Thread’in sadece birtanesine bildirimde bulunur , diger 2 thread waiting durumunda kalir.

Waiter is waiting for the notifier at waiterThread2
Waiter is waiting for the notifier at waiterThread3
Waiter is waiting for the notifier at waiterThread
Notifier is sleeping for 3 seconds at
Notifier is notifying waiting thread to wake up at
Waiter is done waiting at : waiterThread2
Waiter got the message: Notifier took a nap for 3 seconds

Yazimi burada sonlandiriyorum.
Herkese Bol Javali Gunler dilerim.
Be an oracle man , import java.*;
Levent Erguder
OCP, Java SE 6 Programmer
OCE, Java EE 6 Web Component Developer

Print Friendly, PDF & Email

Leave a Reply

Your email address will not be published. Required fields are marked *