Java’da ExecutorService ve Thread Havuzları
Java’da concurrency (eÅŸzamanlılık) ve multithreading (çoklu iÅŸ parçacığı) uygulamalarında, thread yönetimini verimli ve kolay bir ÅŸekilde yapmak çok önemlidir. Bu noktada, Java’nın sunduÄŸu ExecutorService ve thread havuzları devreye girer. ExecutorService, Java’nın thread’leri daha verimli ve kolay yönetebilmek için sunduÄŸu güçlü bir araçtır. Bu yazıda, ExecutorService’in ne olduÄŸunu, thread havuzlarını nasıl kullanacağımızı ve thread yönetimini nasıl daha verimli hale getirebileceÄŸimizi detaylı bir ÅŸekilde ele alacağız.
ExecutorService Nedir?
ExecutorService, Java’nın java.util.concurrent
paketinde bulunan ve thread’lerin yönetimini kolaylaÅŸtırmak amacıyla kullanılan bir arayüzdür. Thread’leri manuel olarak oluÅŸturmak ve yönetmek yerine, ExecutorService kullanarak bu süreci daha kontrollü ve verimli bir ÅŸekilde gerçekleÅŸtirebilirsiniz. ExecutorService, thread’lerin yeniden kullanılmasını saÄŸlayarak sistem kaynaklarının boÅŸa harcanmasının önüne geçer ve aynı anda birden fazla iÅŸlemi daha verimli bir ÅŸekilde yönetmenize yardımcı olur.
ExecutorService Kullanarak Thread Yönetimi
ExecutorService ile bir thread havuzu oluÅŸturabilir ve belirli sayıda thread’in görevleri gerçekleÅŸtirmesini saÄŸlayabilirsiniz. Bu thread’ler iÅŸlerini bitirdikten sonra baÅŸka görevleri almak için yeniden kullanılabilir, böylece her iÅŸ için yeni bir thread oluÅŸturmaya gerek kalmaz.
Örnek: ExecutorService Kullanımı
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(3); // 3 thread'lik bir havuz oluÅŸtur
for (int i = 0; i < 5; i++) {
Runnable worker = new WorkerThread("Görev " + i);
executor.execute(worker); // Thread havuzuna görevleri ekleyin
}
executor.shutdown(); // Yeni görev kabul edilmez, mevcut görevler bitirilir
while (!executor.isTerminated()) {
}
System.out.println("Tüm görevler tamamlandı");
}
}
class WorkerThread implements Runnable {
private String message;
public WorkerThread(String message) {
this.message = message;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " (Başlıyor) : " + message);
processMessage();
System.out.println(Thread.currentThread().getName() + " (Bitti) : " + message);
}
private void processMessage() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Bu örnekte, Executors.newFixedThreadPool(3)
ile 3 thread’lik bir havuz oluÅŸturduk ve 5 farklı görev ekledik. ExecutorService, 3 thread’i kullanarak bu görevleri paralel olarak gerçekleÅŸtirdi. Bu sayede, aynı anda çalışan thread sayısını kontrol edebilir ve kaynakları daha verimli kullanabilirsiniz.
ExecutorService Metotları
ExecutorService, thread yönetimini kolaylaştıran birçok metot sunar. Bu metotlardan bazıları şunlardır:
- execute(Runnable command): Belirtilen görevi thread havuzuna ekler ve mevcut bir thread ile bu görevi çalıştırır.
- shutdown(): Yeni görevlerin kabul edilmesini durdurur, fakat mevcut görevlerin bitirilmesine izin verir.
- shutdownNow(): Tüm görevleri durdurmaya çalışır ve bekleyen görevleri çalıştırmaz.
- isShutdown(): Executor’un kapatılıp kapatılmadığını kontrol eder.
- isTerminated(): Tüm görevlerin tamamlanıp tamamlanmadığını kontrol eder.
Thread Havuzu (Thread Pool) Nedir?
Thread havuzu, bir uygulamada aynı anda çalışan thread sayısını kontrol etmek ve kaynak kullanımını optimize etmek için kullanılan bir tekniktir. Her yeni görev için bir thread oluÅŸturmak yerine, önceden belirlenmiÅŸ sayıda thread’in yeniden kullanılması saÄŸlanır. Bu sayede, thread oluÅŸturma ve yok etme iÅŸlemlerinin getirdiÄŸi maliyet en aza indirgenmiÅŸ olur.
Thread Havuzu Türleri
Java, farklı thread havuzu türleri sunar. Bu havuzlar, farklı kullanım senaryolarına göre seçilebilir:
1. Fixed Thread Pool
Sabit sayıda thread içeren bir havuzdur. Executors.newFixedThreadPool(int nThreads)
kullanılarak oluÅŸturulur. Bu havuz, belirli sayıda thread’in yeniden kullanılmasını saÄŸlar.
ExecutorService fixedPool = Executors.newFixedThreadPool(4);
2. Cached Thread Pool
GerektiÄŸi kadar thread oluÅŸturan ve kullanılmayan thread’leri bir süre sonra serbest bırakan bir havuzdur. Kısa süreli fakat çok sayıda görev içeren durumlarda kullanışlıdır. Executors.newCachedThreadPool()
kullanılarak oluşturulur.
ExecutorService cachedPool = Executors.newCachedThreadPool();
3. Single Thread Executor
Tek bir thread kullanan bir havuzdur. Görevler bir kuyruğa alınır ve sırayla gerçekleştirilir. Executors.newSingleThreadExecutor()
kullanılarak oluşturulur.
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
4. Scheduled Thread Pool
Belirli aralıklarla veya belirli bir süre sonra görevlerin çalıştırılması için kullanılır. Executors.newScheduledThreadPool(int corePoolSize)
kullanılarak oluşturulur.
ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(2);
Fixed Thread Pool vs Cached Thread Pool
- Fixed Thread Pool: Sabit sayıda thread kullanarak belirli sayıda görevi paralel olarak çalıştırır. Sistemin kapasitesine göre kaç thread kullanılacağını ayarlamak mümkündür. Sabit görev sayısının olduğu durumlarda kullanışlıdır.
- Cached Thread Pool: GerektiÄŸi kadar yeni thread oluÅŸturur ve bu thread’ler kullanılmadığında serbest bırakılır. Kısa süreli ve çok sayıda küçük görevler için uygundur, ancak uzun süreli görevlerde çok fazla thread oluÅŸarak sistem kaynakları tüketilebilir.
ExecutorService ve Thread Havuzlarının Avantajları
- Kaynak Yönetimi: Thread’lerin yeniden kullanılması, thread oluÅŸturma ve yok etme maliyetini azaltır. Bu sayede sistem kaynakları daha verimli kullanılır.
- Kolay Yönetim: ExecutorService, thread’lerin yönetimiyle ilgili karmaşıklığı azaltır. Thread’leri manuel olarak yönetmek yerine, görevlerin belirli bir thread havuzunda sıraya alınmasını saÄŸlar.
- Ölçeklenebilirlik: Thread havuzları, iş yükünü dengelemek ve uygulamanın performansını artırmak için ölçeklenebilir bir çözüm sunar.
Örnek: ScheduledExecutorService Kullanımı
ScheduledExecutorService, görevlerin belirli bir süre sonra veya belirli bir aralıkla çalıştırılmasını sağlar. Örneğin, belirli bir görevi her 5 saniyede bir çalıştırmak için kullanılabilir.
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Runnable task = () -> System.out.println("Zamanlı görev çalışıyor: " + System.currentTimeMillis());
scheduler.scheduleAtFixedRate(task, 0, 5, TimeUnit.SECONDS); // Her 5 saniyede bir çalıştır
}
}
Bu örnekte, scheduleAtFixedRate()
metodu ile belirli bir görevi her 5 saniyede bir çalıştırıyoruz. Bu tür kullanım, periyodik görevler için oldukça faydalıdır.
Bu makalede, Java’da ExecutorService ve thread havuzları kullanarak thread yönetimini nasıl daha verimli hale getirebileceÄŸimizi ele aldık. ExecutorService, thread oluÅŸturma ve yönetim iÅŸlemlerini kolaylaÅŸtırarak daha güvenilir ve verimli uygulamalar geliÅŸtirmemize yardımcı olur.
- Sıfırdan PHP’ye: Temel EÄŸitim Serisi ile Programlama Dünyasına Adım Atın
- 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ı