16 Mayıs 2019 Perşembe

Executors.newFixedThreadPool metodu - Unbounded Kuyruk Kullanır OOM Verebilir

Giriş
Bu metodun iki tane overload edilmiş hali bar.
1. Thread Sayısı
İmzası şöyle.
public static ExecutorService newFixedThreadPool(int nThreads)
2. Thread Sayısı + ThreadFactory
Yaratılan her thread'e isim falan verilebiliyor.

Metodun İçi
Metodun için şöyle.

corePoolSize ve maximumPoolSize aynıdır. keepAliveTime 0'dır . Yani Thread hep yaşar.

Kuyruk olarak unbounded kuyruk kullanır. Eğer çok fazla iş eklersek kuyruk unbounded olduğu için bellek bitebilir.
public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
}
LinkedBlockingQueue şöyledir. Yani sınırsız sayıda iş alabilir.
public LinkedBlockingQueue() {
    this(Integer.MAX_VALUE);
}
public LinkedBlockingQueue(int capacity) {...}
Açıklaması şöyle.
Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue. At any point, at most nThreads threads will be active processing tasks. If additional tasks are submitted when all threads are active, they will wait in the queue until a thread is available. If any thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks. The threads in the pool will exist until it is explicitly shutdown.
Ne Zaman Terchi Etmeli

1. Çalıştırılan Thread Sayısına Üst Sınır Vermek İçin Kullanılır
Bu metod verilen servise üst sınır konulmak istenilirse faydalı. Örneğin aynı anda sadece 4 müşteriye hizmet vermek gibi. Böylece patlama anlarında çok fazla thread yaratarak sisteme aşırı yük binmesini engellenebiliyor. Açıklaması şöyle.
Use thread pools to enable graceful degradation of service during traffic bursts
Bu servisi kullanırken dikkat edilmesi gereken tasarım noktası, thread sayısı sınırlı olduğu için yeni işletilmekte olan işin, aynı ExecutorService nesnesine yeni yeni işler ekleyip sonucunun bitmesini beklememesi. Bu durum deadlock (kilitlenme) oluşmasına sebep olabilir. Açıklaması şöyle
Do not execute interdependent tasks in a bounded thread pool
2. Kısa Vadeli İşler İçin Kullanılır
Örneğin yoğun hesaplama yapılan, yani bekleme yapmayan işlerde tercih edilir. Bu Executor tipini Swing uygulamasında kısa vadeli işleri (short term) - ekrana çizilecek şeyi hesaplamak gibi - çalıştırmak için kullandım.

3. Ani Artış (Burst) İşlere İyi Uyum Sağlamaz
Kısa vadeli işlerde kullansak bile sayısal olarak ani artış gösteren işlere iyi uyum sağlamaz. Thread sayısı sabit olduğu için hepsi meşgülse işe cevap süresi uzun olabilir.

İdeal Kullanım
Veritabanındaki tabloya yazılan işleri arka tarafta (back end) işleyen asenkron işler için mükemmel bir yöntem. Sistemdeki çekirdek sayısı kadar thread açılır ve her thread tablodan okuma yapar işi çalıştırır.

Kullanım
Örnek - int
Şöyle yaparız.
ExecutorService executorService = Executors.newFixedThreadPool(3);
Örnek - int
Hem sadece 4 müşteriye hizmet verip hem de toplamda da sınırlı sayıda iş kabul etmek istersek şöyle yaparız. Eğer üst sınır aşılırsa RejectedExecutionException fırlatılır.
public static
ExecutorService newFixedThreadPoolWithQueueSize(int nThreads, int queueSize) {
  return new ThreadPoolExecutor(nThreads, nThreads,
                              5000L, TimeUnit.MILLISECONDS,
                              new ArrayBlockingQueue<Runnable>(queueSize, true));
}
Örnek - int + ThreadFactory
Thread'e isim vermek için kullanılabilir. 
Şöyle yaparız.
String someName="fileName"; // Inside first file 
...........................
.........................

Executors.newFixedThreadPool(30, new 
           ThreadFactoryBuilder().setNameFormat(someName).build());
Daha karmaşık örnekler burada.

Hiç yorum yok:

Yorum Gönder