Pure Java – 85 Thread – 02

Merhaba Arkadaslar,
Onceki yazida Java’da Thread konusuna giris yaptik, thread kavramindan bahsettik. Bu bolumde Thread’i calistirmayi inceleyecegiz.
Hatirlayacagimiz gibi yeni baslayan bir thread yeni bir Stack meydana getirecektir. Thread’i baslatmak icin start() metodunu kullaniriz.

t.start();
  • t, java.lang.Thread sinifi tipinde referans degiskendir.
  • Thread’in baslamasi yeni bir stack olusturur.
  • Thread “new” durumundan “runnable” durumuna gecer.
  • Runnable duruuna gectikte sonra run() metodunu calistirilabilir.

Unutmayalim, Thread ‘i baslatabiliriz(start) , Runnable’i baslatmak(start) kavrami soz konusu degildir. Bu nedenle start metodu java.lang.Thread sinifinin ornegi/instance uzerinden(Thread tipinde referans degisken araciligiyla ) olur.

Basit bir ornek ile baslayalim.

public class MyThread extends Thread {

	@Override
	public void run() {
		System.out.println("This is run() method!");
	}

	public static void main(String[] args) {

		MyThread thread = new MyThread();
		thread.start();

	}
}

Hatirlayacagimiz gibi java.lang.Thread sinifi java.lang.Runnable arabirimini uygulamaktadir.
Runnable arabirimi run() metoduna sahiptir. Burada run() metodunu override ettik ve yapilmasi gereken isi burada belirttik.

  • start() metodu yeni bir thread ve stack baslatir daha sonrasinda run metodunu cagirir.
  • run() metodunu direkt cagirmak yeni bir thread ve stack olusturmaz fakat legal bir durumdur. Birden fazla run metodunu cagirabiliriz.
  • run() metodunu cagirmak diger metotlari cagirmak gibidir, dolayisiyla diger metotlarda oldugu gibi ayni mevcut/current stack icerisinde calisir/yasar.
  • Unutmayalim instance metotlar Stack’te yasarlar.
  • start() metodunu bir referans degisken uzerinden cagirdiktan sonra , tekrar start metodunu cagirdigimizda java.lang.IllegalThreadStateException hatasi aliriz.
public class MyThread extends Thread {

	@Override
	public void run() {
		System.out.println("This is run() method!");
	}

	public static void main(String[] args) {

		MyThread thread = new MyThread();
		thread.start();

		thread.run();
		thread.run();

		// thread.start();
		// java.lang.IllegalThreadStateException

	}
}

Benzer ornegimizi Runnable arabirimini kullanarak da yapabiliriz.

class MyRunnableThread implements Runnable {

	@Override
	public void run() {
		System.out.println("This is Runnable run metot");
	}

}

public class RunnableTest {

	public static void main(String[] args) {

		MyRunnableThread myRunnable = new MyRunnableThread();
		Thread t = new Thread(myRunnable);
		t.start();

	}
}

Simdi de birden fazla Thread ile calisan kucuk bir ornek yazalim;

class MyRunnableMoreThread implements Runnable {

	@Override
	public void run() {
		System.out.println("run method()");
		for (int i = 0; i < 10; i++) {
			String name = Thread.currentThread().getName();
			long id = Thread.currentThread().getId();
			System.out.println("index:" + i + " " + name + " " + id);
		}
	}

}

public class RunnableMoreThreadTest {

	public static void main(String[] args) {

		MyRunnableMoreThread myRunnable = new MyRunnableMoreThread();
		Thread t1 = new Thread(myRunnable);
		Thread t2 = new Thread(myRunnable);
		Thread t3 = new Thread(myRunnable);

		t1.setName("First");
		t2.setName("Second");
		t3.setName("Third");

		t1.start();
		t2.start();
		t3.start();

	}
}

Ornegimizi incelersek t1, t2, t3 isimlerine sahip 3 tane Thread referans degiskenleri olusturduk. Bu referans degiskenleri olustururken myRunnable referans degiskenini Thread sinifinin yapilandiricisina arguman olarak verdik.

setName metodu ile threadlere isim verebiliriz. Sonrasinda start metodunu her bir referans degisken icin cagirdik.

Thread.currentThread() o an calisan Thread’i doner. Ornegimizi calistirdigimizda suna benzer bir cikti aliriz;

run method()
run method()
index:0 First 9
index:1 First 9
index:2 First 9
index:3 First 9
index:0 Second 10
index:4 First 9
run method()
index:0 Third 11
….

Bu ciktinin bir GARANTISI yoktur! Burada hangi thread’in once calisacagi, hangisinin ne kadar calisacaginin(duration) bir garantisi yoktur. Bir thread baslatiktan sonra isi bitmeden(run metodu tamamlanmadan) digeri baslayabilir/calisabilir. Burada onemli nokta her bir thread icin run() metodu tamamlanacaktir.

Bir thread calismasini sonlandirdiginda(run metodu tamamlandiginda) olu/dead duruma gecer. Teknik olarak API de karsiligi TERMINATED durumudur. Bununla birlikte Thread objesi hala yasamaktadir. Thread in TERMINATED durumda olmasi objenin silinmesine neden olmaz.

Bir thread TERMINATED duruma geldiginde artik yeniden baslatilamaz. Bir thread referans degikseni uzerinden 2.kez start() metodunu cagiramayiz bu durumda IllegalThreadStateException hatasi aliriz. Bir thread yeniden baslatilamaz.

run metodunu cagirmak yeni bir thread baslatmaz, diger metot cagrilmalari gibi ayni stack uzerinde cagrilir. start metotlarini run metodu olarak degistirirsek;

		t1.run();
		t2.run();
		t3.run();

run method()
index:0 main 1
index:1 main 1
index:2 main 1
index:3 main 1
index:4 main 1
index:5 main 1
index:6 main 1
index:7 main 1
index:8 main 1
index:9 main 1
run method()
index:0 main 1
index:1 main 1
index:2 main 1
index:3 main 1
….

Ciktiyi inceledigimiz zaman sadece “main” threadi calismaktadir. Bununla birlikte burada sonuc/cikti GARANTIDIR. Diger metot cagrilmalarinda oldugu gibi calisacaktir. run metodu ilk kez cagrildiktan sonra bittikten sonra 2 ve 3.kez cagrilacaktir.

Thread Scheduler
Thread Scheduler, JVM’in bir parcasidir.
Thread Scheduler hangi eligible/uygun/secilebilir “thread” in calistirilacagina karar verir. Eligible/uygun thread’ten kasit runnable state/durumdaki threadlerdir.

Runnable State’e sahip threadler , JVM tarafindan calistirilabilir/aktif halde is yapar. Runnable durumda hali hazirda calisan thread(currently running thread) durumuna gecemezler.

Hangi runnable state’e sahip thread’in secilecegine dair bir garanti yoktur. Burada queue/kuyruk mantigi da gecerli degildir, garanti yoktur. Yani 1.thread calisti sonra 2.thread calisti 3.thread calismadan tekrar 1.thread o an calisabilir.
Thread’leri runnable queue yerine runnable pool olarak dusunebiliriz.

Thread Scheduler bizim kontrolumuzde degildir, JVM tarafindan kontrol edilir. Sadece bazi metotlar yardimi ile bu schedule islemini etkileyebiliriz(influence)

java.lang.Thread

public static void sleep(long millis) throws InterruptedException
public static void yield()
public final void join() throws InterruptedException
public final void setPriority(int newPriority)

java.lang.Object

public final void wait() throws InterruptedException 
public final native void notify();
public final native void notifyAll();

Bu metotlari ilerleyen yazilarda inceleyecegiz.

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 *