Thread sayısının ve çalışmasının düzenli ve kontrollü bir şekilde gerçekleştirilmesi için Java bize Executor adında bir sınıf sunmaktadır.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ThreadLesson2 {
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 20; i++) {
Thread thread = new Thread(new MyThread("thread" + i, 3));
executor.execute(thread);
}
executor.shutdown();
executor.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("Done");
}
}
ExecutorService bize belli bir anda en fazla kaç Thread çalıştırmak istediğimizi sormaktadır. Yukarıdaki örnek newFixedThreadPool metodu ile 5 farklı iş parçasının aynı anda çalıştırılabileceği belirtilmiştir. Daha sonrasında for döngüsü içinde 20 adet Thread tanımlanmasına rağmen executor servisi gelen işleri düzene sokar ve 5 Thread üzerinde işlem gerçekleştirmez. Sonradan eklenen işlemler sıraya (queue) sokulur ve mevcut işlemler bitirildikçe çalıştırılır. Böylece sistem kaynakları işlem parçaları tarafından kontrolsüzce harcanamaz. shutdown metodu ise yeni işlem alımını durdurur ve mevcut işlemlerin bitirilmesini sağlar. awaitTermination ise mevcut işlemlerin bitirilmesi için belirli bir süre tanır ve bu sürenin sonunda ExecutorService tamamen kapatılır.
Tanımlanan işlemlerin belirli bir zaman sonra otomatik başlatılması ya da sistematik olarak belli bir frekansla çalıştırılması için Java bizlere ScheduledExecutorService adında bir sınıf sunar. Bu sistem sayesinde yapılan işlemlerin belirli bir tarihte başlamasını ya da sürekli olarak işlemin tekrar edilmesini sağlayabiliriz.
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ThreadLesson3 {
public static void main(String[] args) throws InterruptedException {
ScheduledExecutorService pool = Executors.newScheduledThreadPool(5);
MyThread worker = new MyThread("Thread 1", 3);
pool.schedule(worker, 5, TimeUnit.SECONDS);
Thread.sleep(20000);
pool.shutdown();
}
}
Yukarıdaki örnekte ExecutorService yerine ScheduledExecutorService kullanılarak işlemin ileri bir tarihte gerçekleşmesi sağlanır. schedule metodu ile verilen iş parçası 5 saniye gecikmeli çalışacaktır. Thread.sleep metodu ise ana akışı durdurur ancak MyThread ile tanımlanan worker iş parçası ScheduledExecutorService tarafından çalıştırılmaktadır. Konsol çıktısı aşağıdaki gibidir;
Thread 1 : 0
Thread 1 : 1
Thread 1 : 2
Dilerseniz scheduleAtFixedRate metodu ile işlemin sürekli çalışmasını sağlayabilirsiniz.
NOT : Zamanlama işlemleri için Java'da Timer adında bir sınıf da kullanılmaktadır, ancak Android uygulamalarında zamanlayıcılar için ScheduledExecutorService kullanılması tavsiye edilmektedir.