-- Java SE

Thread Pool

Daha önceki yazılarda taskın ve threadın şu şekilde Runnable task = new TaskClass(task); new Thread(task).start();  oluşturalabileceğini yazmıştım.

Bu yöntem tek taskı yerine getiren uygulamarda kullanışlı olsa da çokça task olan uygulamarla her task için bir thread oluşturmak gerektiğinden elverişli olmayacaktır. Her task için yeni bir thread başlatmak performans sorunlarına yol açar. Thread pool işte burada devreye giriyor.

Javada taskları bir thread pool içinde halletmek için Executor interface’i ve bu taskları kontrol edebilmek için ExecutorService subinterface’i vardır. ExecutorService, Executor’in alt interface’idir.

Bir Executor nesnesi oluşturmak için Executors sınıfı içerisindeki static metodlar kullanılır. newFixedThreadPool(int) metodu pool içerisinde sabit sayıda thread oluşturmak için kullanılır. Eğer bir thread bir taskı bitirmişse (boştaysa) başka bir task için yeniden kullanılabilir. Eğer ki bir thread kapanmadan önce bir hatayla karşılaştıysa ve hala yapılması gereken bir task varsa, bu threadın yerini alması için yeni bir thread oluşturulur.(pool içerisindeki taskların boşta olmaması durumunda).
newCachedThreadPool() metodu ile pooldaki tüm threadlar meşgulse ve sırada yapılması gereken tasklar varsa yeni threadlar oluşturulur Ancak cached pool içerisindeki threadlar 60 saniye sonra kapanıyor. Cached pool kısa sürecek tasklar için kullanışlıdır.

Önceki yazıdaki printNum ve printChar sınıfları şu şekildeydi :

public class PrintChar implements Runnable { private char charToPrint; // yazılacak karakter private int times; // kaç kere yazılacak? public PrintChar(char c,int t){ charToPrint = c; times = t; } @Override public void run() { for (int i = 0; i < times; i++){ System.out.print(charToPrint); } } }

public class PrintNum implements Runnable {

    private int lastNum; // kaça kadar sayılar yazılacak?

    public PrintNum(int n) {

        lastNum = n;
    }


    @Override
    public void run() {

        for (int i = 1; i <= lastNum; i++) {
            System.out.print(" " + i);
        }
    }
}

Main metodunu içeren sınıfı değiştirerek thread pool’a uygun hale getirelim.

mport java.util.concurrent.*;

public class ExecuterDemo {

    public static void main(String args[]){

        ExecutorService executor = Executors.newFixedThreadPool(3);

        executor.execute(new PrintChar('a',100));
        executor.execute(new PrintChar('b', 100));
        executor.execute(new PrintNum(100));

        executor.shutdown();
    }
}

7. satırda maximum 3 threadlı bir pool oluşturuluyor. 9,10 ve 11. satırlarda printChar ve printNum taskları oluştulup poola ekleniyor.

Bu şekildeki bir kodlamada executor 3 adet thread oluşturur ve tasklar eş zamanlı olarak halledilir.

  • Eğer ki 7. satıdaki 3 parametreli metod yerine ExecutorService executor = Executors.newFixedThreadPool(1);  yazılsaydı bu 3 runnable task sıralı olarak halledilecekti.Çünkü poolda sadece bir thread olacaktı.
  • Eğer ki 7. satıdaki 3 parametreli metod yerineExecutorService executor = Executors.newCachedThreadPool();  yazılsaydı her bekleyen task için yeni bir thread oluşturulacaktı,3 task olduğu için 3 thread oluşturulacaktı ve bu threadlar eş zamanlı olarak çalışacaktı.

shutdown() metodu executor’a kapanmasını söyler. Yeni tasklar kabul edilmez ancak daha önceden tanımlanmış tasklar bitmesi için devam eder.

NOT : Eğer tek bir task için thread oluşturulacaksa Thread classını, birden çok task için thread oluşturalacaksa thread pool kullanmakta fayda var.

Yorum bırak

Yorum