Pure Java – 87 Thread – 04

Merhaba Arkadaslar,

Onceki bolumde Thread State’lerini inceledik. Bu bolumde java.lang.Thread sinifinda yer alan su metotlari inceleyecegiz;

  • sleep
  • yield
  • join

sleep
java.lang.Thread sinifinda overloaded 2 tane sleep metodu yer almaktadir.

public static native void sleep(long millis) throws InterruptedException;
public static void sleep(long millis, int nanos)

Burada dikkat edilecek nokta;

  • sleep metodu static bir metottur.
  • sleep metodu checked bir exception olan InterruptedException firlatabilir. Dolayisiyla bu metodu cagirdigimiz yerde handle or declare kuralina uymamiz gereklidir.
  • Birinci metot native bir metottur ve long tipinde parametre almaktadir. sleep native metodu JVM tarafindan uygulanir.
  • 1 saniye 1000 milisaniyedir.
  • Ikinci metot long tipinde ve int tipinde parametre almaktadir. Bu metotta milisaniye+nanosaniye olarak uyuma/sleep suresi belirlenir. 1 milisaniye 1000000(10^6) nanosaniyedir. Ikinci metot birinci sleep metodunu cagirir.
    public static void sleep(long millis, int nanos)
    throws InterruptedException {
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }

        sleep(millis);
    }

Thread.sleep metodu , hali hazirda calisan Thread’i, arguman olarak verilen belirtilmis sure kadar askiya alir(suspend)/uyutur.

sleep metodunda belirtilmis sure bittiginde , tekrar calismaya devam edeceginin bir garantisi yoktur. Bu sure bittiginde uyutulmus thread, timed_waiting durumundan runnable durumuna gecer. Thread Scheduler tarafindan calistirilmak icin tekrar uygun hale gelir(eligible).

Dolayisiyla “minimum” , arguman olarak verilen sure kadar ilgili thread calismayacaktir.

Unutmayalim; sleep metodu static metottur. t , Thread tipinde bir referans degisken olsun. t referans degiskeni uzerinden sleep metodunu cagirmak bu thread’i sleep durumuna gecirmez ! sleep metodu cagrildigi noktada hali hazirda calisan thread’i sleep durumuna gecirir!

Thread.sleep(1000);
t.sleep(1000);

Simdi basit bir ornek yapalim, 3 tane thread olusturalim , run metodunda 500milisaniye(0.5 saniye) olacak sekilde sleep metodunu kullanalim.

public class ThreadSleepTest implements Runnable {

	public static void main(String[] args) {
		ThreadSleepTest sleepTest = new ThreadSleepTest();

		Thread thread1 = new Thread(sleepTest);
		Thread thread2 = new Thread(sleepTest);
		Thread thread3 = new Thread(sleepTest);

		thread1.setName("myThread1");
		thread2.setName("myThread2");
		thread3.setName("myThread3");

		thread1.start();
		thread2.start();
		thread3.start();
	}

	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			System.out.println("Thread name :" + Thread.currentThread().getName() + " index:" + i);
			try {
				Thread.sleep(500);
				// sleep metodu 0.5 saniye hali hazirda calisan thread'in
				// durumunu sleeping(timed_waiting) yapacaktir.
			} catch (InterruptedException e) {
				System.out.println("exception handled");
			}
		}
	}
}

Burada ciktinin/output (oncelik acisindan) bir garantisi yoktur.

Thread.sleep metodunu kodumuzda her yerde cagirabiliriz. main metodu calistiginda “main” ismine sahip thread calisacaktir. Burada calisan main threadini 3 saniye sleep durumuna gecirebiliriz.

public class ThreadMainTest {

	public static void main(String[] args) {
		System.out.println("Before calling sleep");

		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		System.out.println("After calling sleep");

	}
}

priority & yield
Thread’lerin sahip oldugu bir priority(oncelik) degeri vardir. Bu deger genel olarak 1-10 arasinda degismektedir, fakat farkli Thread Schedulerlar icin bu deger 10dan kucuk de olabilir.

JVM , preemptive(sonsuz oncelikli), priority-based bir schedule algoritmaya sahiptir. Bu JVMlerde time-slicing(zaman dilimi) scheduler yaklasimini uygulanir.

Bununla birlikte tum JVM’lerde time-slicing yaklasimi uygulanmak zorunda degildir. JVM spesifikasyonu time-slicing scheduler uygulanmasini sart kosmaz.

Bir cok JVM icin threadlerin priority degeri onemlidir. Birden fazla thread runnable durumundaysa yuksek oncelige(priority) sahip thread running durumuna gecirilmek icin tercih edilebilir.

Bununla birlikte , bu durumun bir garantisi yoktur.
Priority degerleri daha etkili/verimli program olmasi acisindan kullanilabilir fakat oncelik siralamasi garanti bir sekilde calismayacaktir.

MAX_PRIORITY , MIN_PRIORITY , NORM_PRIORITY degerlerine ve “main” threadinin priority degerlerine goz atalim;

public class PriorityTest {

	public static void main(String[] args) {
		System.out.println(Thread.MAX_PRIORITY);
		System.out.println(Thread.MIN_PRIORITY);
		System.out.println(Thread.NORM_PRIORITY);
		System.out.println(Thread.currentThread().getPriority());
	}
}

setPriority metodunu kullanarak threadlere priority(oncelik) degeri verebiliriz.

public class ThreadPriorityTest implements Runnable {

	@Override
	public void run() {
		for (int i = 0; i < 10000; i++) {
			System.out.println(Thread.currentThread().getName() + " index:" + i);
		}
	}

	public static void main(String[] args) {
		ThreadPriorityTest sleepTest = new ThreadPriorityTest();

		Thread thread1 = new Thread(sleepTest);
		Thread thread2 = new Thread(sleepTest);
		Thread thread3 = new Thread(sleepTest);

		thread1.setName("myThread1");
		thread2.setName("myThread2");
		thread3.setName("myThread3");

		thread1.setPriority(10);
		thread2.setPriority(1);
		thread3.setPriority(5);

		thread1.start();
		thread2.start();
		thread3.start();
	}

}

Simdi de yield metodunu inceleyelim ;

public static native void yield();

yield kelimesinin bir cok turkce anlami vardir buraya en uygun olani yerini birakmak/geri cekilmek olacaktir.

yield metodu cagrildiginda , hali hazirda calisan metot geri cekilir(runnable duruma) gecer ve yerini ayni priority degere sahip bir threade birakir.

yield metodu sleeping/waiting/blocking gibi durumlara neden olmaz. Bununla birlikte tabi yield metodunun da bir garantisi yoktur. Schedule bu istegi gormezden gelebilir(ignore).

yield metodunu kullanmak cogu zaman pek kullanisli ve uygun olmayacaktir(appropriate). Test amacli ve debug amacli kullanilabilir(race condition test).

join

join metodu , bir thread bitene kadar(run metodu sonlana kadar) diger thread lerin beklemesini saglar.

  • sleep ve yield metotlarinin aksine join metodu non-static bir metotdur.
  • join metodu InterruptedException firlatabilir.
  • 3 tane overloaded versiyonu vardir.
   public final void join() throws InterruptedException 
   public final synchronized void join(long millis)
   public final synchronized void join(long millis, int nanos)

1.metot islem bitene kadar bekleyecektir. 2.metot verilen sure(milisaniye) kadar bekleyecektir. 3.metot da verilen sure(milisaniye+nanosaniye) kadar bekleyecektir.

join() metodu cagrildiginda, hali hazirda calisan thread(currenct thread) , thread1 thread’i islemini bitirene kadar bekleyecektir(wait).

thread1.join();

Simdi de join olmadan ve join kullanarak basit bir ornek yapalim.

public class ThreadWithoutJoinExample implements Runnable {

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

	public static void main(String[] args) {

		ThreadWithoutJoinExample runnable = new ThreadWithoutJoinExample();

		Thread thread1 = new Thread(runnable);
		Thread thread2 = new Thread(runnable);
		Thread thread3 = new Thread(runnable);

		thread1.setName("myThread1");
		thread2.setName("myThread2");
		thread3.setName("myThread3");

		thread1.start();
		thread2.start();
		thread3.start();
	}

}

Burada 3 tane thread kullandik , cikti/output tahmin edilemez.

Thread name:myThread1 index:0
Thread name:myThread2 index:0
Thread name:myThread1 index:1
Thread name:myThread2 index:1
Thread name:myThread1 index:2
Thread name:myThread2 index:2
Thread name:myThread1 index:3
Thread name:myThread2 index:3
Thread name:myThread1 index:4
Thread name:myThread2 index:4
Thread name:myThread3 index:0
….

Simdi de join kullanalim;

public class ThreadJoinExample implements Runnable {

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

	public static void main(String[] args) throws InterruptedException {

		ThreadJoinExample runnable = new ThreadJoinExample();

		Thread thread1 = new Thread(runnable);
		Thread thread2 = new Thread(runnable);
		Thread thread3 = new Thread(runnable);

		thread1.setName("myThread1");
		thread2.setName("myThread2");
		thread3.setName("myThread3");

		thread1.start();
		thread1.join();
		// thread1 bitene kadar baska thread calismaz.

		thread2.start();

		thread2.join();
		// thread2 bitene kadar baska thread calismaz.
		
		thread3.start();

	}

}

Bu ornegimizde thread1.join diyerek bu thread bitene kadar diger thread’lerin calismasina engel oluyoruz. Bittikten sonra thread2.join digerek diger threadlerin calismasina engel oluyoruz. Bu durumda ciktimiz her defasinda ayni olacaktir ve sirali bir sekilde yazacaktir.

Thread name:myThread1 index:0
Thread name:myThread1 index:1
Thread name:myThread1 index:2
Thread name:myThread1 index:3
Thread name:myThread1 index:4
Thread name:myThread1 index:5
Thread name:myThread1 index:6
Thread name:myThread1 index:7
Thread name:myThread1 index:8
Thread name:myThread1 index:9
Thread name:myThread2 index:0
Thread name:myThread2 index:1
Thread name:myThread2 index:2
Thread name:myThread2 index:3
Thread name:myThread2 index:4

sleep , yield ve join metodunu kisaca ozetleyecek olursak ;

sleep metodu , hali hazirda calisan threadin(current thread) ,InterruptedException olmadigi surece, “en az” belirtilen sure kadar(milisaniye ya da milisaniye+nanosaniye) kadar uyumasini saglayacaktir(timed_waiting). “en az” olmasinin nedeni sure biter bitmez tekrar calisacaginin bir garantisi yoktur. Sure bittiginde thread , timed_waiting durumundan den runnable duruma gecer. Dolayiyisla Thread Scheduler tarafindan secilmeye uygun hale gelir.

yield metodunun bir garantisi yoktur. Hali hazirda calisan threadin geri cekilmesini(yield) ve yerini ayni priority degerine sahip baska bir threadin running duruma gecmesi icin Thread Scheduler’a oneride bulunur. Thread Scheduler bu metodu gormezden gelebilir(ignore).

join metodu , bir thread bitene kadar(run metodu sonlana kadar) diger thread lerin beklemesini saglar.

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 *