Java’da Thread Yönetimi ve Thread Durumları Nelerdir?
Java’da thread’ler farklı durumlarda bulunabilir ve bu durumlar thread’in yaşam döngüsünün bir parçasıdır. Bir thread’in yönetilmesi ve farklı durumlardaki geçişleri anlamak, Java’da concurrency (eşzamanlılık) ile uğraşırken kritik bir öneme sahiptir. Bu yazıda, Java’da thread yönetimi ve thread durumları üzerine detaylı bir inceleme yapacağız. Java’da thread’in çeşitli durumları (thread states) ve bu durumların ne anlama geldiği hakkında bilgi edineceğiz.
Thread’in Yaşam Döngüsü
Java’da bir thread, oluşturulmasından itibaren çeşitli durumlardan geçer. Bu durumlar, bir thread’in çalışma süresince belirli bir noktada ne yaptığını veya hangi aşamada olduğunu gösterir. Thread’ler beş ana durumda bulunabilir:
- NEW (Yeni): Thread oluşturulmuş fakat henüz başlatılmamış durumda.
- RUNNABLE (Çalışabilir): Thread çalışmaya hazır veya çalışıyor. CPU tarafından işlenmeyi bekliyor olabilir.
- BLOCKED (Bloklanmış): Thread, bir kilidi (lock) elde etmek için bekliyor.BLOCKED (Bloklanmış): Thread, bir kilidi (lock) elde etmek için bekliyor.
- WAITING (Bekliyor): Thread başka bir thread’in bir eylemi tamamlamasını bekliyor.
- TIMED_WAITING (Zamanlı Bekliyor): Thread belirli bir süre boyunca beklemeye alınmış.
- TERMINATED (Sonlanmış): Thread görevini tamamlamış ve çalışması bitmiş.
Bu durumları ve aralarındaki geçişleri daha iyi anlamak, thread’lerin doğru şekilde yönetilmesi için çok önemlidir.
1) NEW (Yeni)
Bir thread Thread
sınıfının bir örneği oluşturularak yaratıldığında, fakat henüz start()
metodu çağrılmadığında, thread NEW durumundadır.
Örnek:
Thread thread = new Thread(() -> {
System.out.println("Thread çalışıyor");
});
System.out.println("Durum: " + thread.getState()); // NEW
Bu durumda thread oluşturulmuş ancak henüz çalışmaya başlamamıştır.
2) RUNNABLE (Çalışabilir)
start()
metodu çağrıldıktan sonra thread RUNNABLE durumuna geçer. RUNNABLE durumda olan bir thread, CPU tarafından çalıştırılmayı bekler veya aktif olarak çalışıyordur. Java’da RUNNABLE durumu hem CPU tarafından çalıştırılmayı bekleyen hem de aktif çalışan thread’leri içerir.
Örnek:
Thread thread = new Thread(() -> {
System.out.println("Thread çalışıyor...");
});
thread.start();
System.out.println("Durum: " + thread.getState()); // RUNNABLE
start()
metodunun çağrılması ile thread, çalışmaya başlamak için sıraya girer ve RUNNABLE duruma geçer.
3) BLOCKED (Bloklanmış)
Bir thread, ortak bir kaynağı (örneğin bir metod veya nesne) kilitlemek için başka bir thread’in kilidi serbest bırakmasını beklerken BLOCKED duruma geçer. Genellikle synchronized
anahtar kelimesi ile korunan bir kaynağa erişmeye çalışan thread’ler bloklanabilir.
Örnek:
public class Main {
private static final Object lock = new Object();
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
synchronized (lock) {
System.out.println("Thread 1 kilidi aldı");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread thread2 = new Thread(() -> {
synchronized (lock) {
System.out.println("Thread 2 kilidi aldı");
}
});
thread1.start();
thread2.start();
}
}
Bu örnekte, thread1
kilidi aldıktan sonra thread2
, aynı kilidi serbest bırakana kadar BLOCKED durumda kalacaktır.
4) WAITING (Bekliyor)
Bir thread, başka bir thread’in bir işlemi tamamlamasını beklerken WAITING durumuna geçer. Bu duruma Object.wait()
veya Thread.join()
gibi yöntemler neden olabilir. WAITING durumu, belirli bir süre belirtilmeden, sınırsız olarak sürebilir.
Örnek:
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(() -> {
try {
Thread.sleep(1000);
System.out.println("Thread 1 tamamlandı");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread thread2 = new Thread(() -> {
try {
thread1.join(); // thread1'in tamamlanmasını bekle
System.out.println("Thread 2 çalışıyor");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread1.start();
thread2.start();
}
}
Bu örnekte, thread2
, thread1
tamamlanana kadar WAITING durumunda kalacaktır. join()
metodu ile thread2
, thread1
bitmeden çalışmaya başlamaz.
5) TIMED_WAITING (Zamanlı Bekliyor)
Bir thread belirli bir süre boyunca beklemeye alındığında TIMED_WAITING durumuna geçer. Bu duruma Thread.sleep(long millis)
, Object.wait(long timeout)
veya Thread.join(long millis)
gibi yöntemler neden olabilir.
Örnek:
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
try {
Thread.sleep(3000); // 3 saniye bekle
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread.start();
Thread.sleep(1000); // thread'in durumu kontrol edilmeden önce 1 saniye bekle
System.out.println("Durum: " + thread.getState()); // TIMED_WAITING
}
}
Bu örnekte, thread
3 saniye boyunca bekletilir ve bu sırada durumu TIMED_WAITING olacaktır.
6) TERMINATED (Sonlanmış)
Bir thread, çalışmasını tamamladığında TERMINATED durumuna geçer. Bu durumda, thread ya normal bir şekilde tamamlanmış ya da bir hata nedeniyle sonlanmış olabilir.
Örnek:
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
System.out.println("Thread çalışıyor...");
});
thread.start();
thread.join(); // Thread'in bitmesini bekle
System.out.println("Durum: " + thread.getState()); // TERMINATED
}
}
Bu örnekte, thread
görevini tamamladıktan sonra TERMINATED durumuna geçer.
Thread Durumları Arasındaki Geçişler
Bir thread, yaşam döngüsü boyunca bir durumdan diğerine geçiş yapar. Bu geçişler şu şekildedir:
- NEW → RUNNABLE:
start()
metodu çağrıldığında. - RUNNABLE → BLOCKED: Bir kilit elde edilemediğinde.
- RUNNABLE → WAITING/TIMED_WAITING:
wait()
,join()
, veyasleep()
metodları çağrıldığında. - RUNNABLE/WAITING → TERMINATED:
run()
metodu sonlandığında veya bir istisna oluştuğunda.
Bu geçişleri anlamak, thread’lerin davranışını tahmin edebilmek ve thread yönetimini daha iyi yapabilmek için önemlidir.
Bu makalede, Java’da thread yönetimi ve thread state’leri detaylı bir şekilde ele aldık. Thread’lerin yaşam döngüsünde geçirdiği durumları, bu durumlar arasındaki geçişleri ve her bir duruma dair örnekleri inceledik. Bu bilgiler, çoklu iş parçacığı kullanımı ile çalışan Java geliştiricileri için kritik önem taşımaktadır.
- Java Concurrency ve Multithreading Bölüm 5: Asenkron Akış ve Reactive Programming
- Java Concurrency ve Multithreading Bölüm 4: CompletableFuture ile Asenkron İşlemler
- Milyon Dolarlık Yazılım Projesi: PHP ile Adım Adım Geliştirme
- Java Concurrency ve Multithreading Bölüm 3: ExecutorService ve Thread Havuzları
- Milyon Dolarlık Bir Proje Kodluyoruz