Java’da Thread

Fatma Delen
3 min readDec 26, 2020

--

Merhabalar,

Bugün sizlere threadlerden bahsedeceğim.

Eşzamanlı uygulamalar geliştirme : Process ve Thread nedir?

Eşzamanlı uygulamalar geliştirmede iki temel işlem birimi karşımıza çıkmaktadır : Process ve thread.

Process(işlem), kendisine ait kaynakları bulunan işlem birimidir.(Her process kendisine ait hafıza alanına sahiptir.)

Thread(iş parçacığı), processler gibi işlem birimleridir. Daha az kaynağa ihtiyaç duyarlar ve threadler bir processin içinde yer alır.(Mutlaka bir processe sahiptir ve onun kaynağını kullanır.) Aynı process ortamında birden fazla iş yürütme imkanı sağlar.

Bir processin çalışmaya başlama anıyla birlikte bir thread(main thread) oluşturulur ve process içinde birden fazla(multi) thread oluşturulabilir.

Öncelikle Java’da thread nasıl oluşturulur ona bakalım :)

1- Thread sınıfından extends alarak

Şimdi bu threadi nasıl çalıştıracağımıza bakalım:

veya ExecutorService kullanarak çalıştırabiliriz:

2- Runnable arayüzünü implement ederek:

Threadlerin Yaşam Döngüsü

Yaşam döngüleri boyunca threadler farklı durumlardan geçer:

—-NEW Oluşturulmuş ancak henüz başlamamış yeni thread.

Thread obje olarak oluşturulur ve start() yöntemini kullanarak başlatana kadar bu durumda kalır.

log’da Thread state: NEW yazdığını görürüz.

—-RUNNABLE — Çalışan veya çalışmaya hazır ama kaynağı bekleyen thread

Thread start() metoduyla çağırılınca runnable(koşturulabilir) olur. Bu esnada thread üstüne düşen görevini yapar.

log’da Thread state: RUNNABLE yazdığını görürüz.

—-BLOCKED — Running durumunda olan bir thread wait(), sleep(), join() metodları çağırılarak blocked veya waiting durumuna geçebilir. Bu esnada işlem yapmaz.

Şu anda çalıştırmaya uygun olmayan bir iş parçacığı BLOCKED durumdadır. Bir monitör kilidi beklediğinde ve başka bir thread tarafından kilitlenen bir kod bölümüne erişmeye çalışırken bu duruma girer.

—-WAITING — Thread’in koşması için başka bir thread’in işini bitirmesini beklemesi durumdur.

—-TIMED_WAITING — Thread’in koşması için başka bir thread’i belli bir süre beklemesi durumdur.

—-TERMINATED — İşlemi bitince thread’ler yok edilir.

Bu, ölü bir thread durumudur. Thread yürütmeyi bitirdiğinde veya anormal şekilde sonlandırıldığında TERMINATED durumundadır.

Executor ile Thread Kullanımı

ExecutorService, kendisine görev atamak için otomatik olarak bir thread havuzu ve API sağlar. Oluşturmak için 2 yöntem vardır:

Bunlardan ilki Executors sınıfında bulunan static factory metotlardır. İkincisi ise direk ThreadPoolExecutor sınıfının yapılandırıcısını kullanmaktır.

1 — Executors Sınıfındaki Static Metodları Kullanarak Oluşturma:

Executors.newFixedThreadPool(int n) : n sayıda thread oluşturup havuzda saklar.

Executors.newCachedThreadPool(): Belirsiz sayılı bir thread havuzu oluşturur. Bir task geldiğinde yeni bir thread oluşturur ve bu thread 60 saniye boyunca havuzda kalır. Yeni bir iş geldiğinde, eğer boşta bir thread var ise, o kullanılır. Boşta thread yok ise yaratılır.

Executors.newSingleThreadExecutor(): Tek bir thread oluşturur ve birim zamanda tek bir iş yürütür.

2 — ThreadPoolExecutor Sınıfı İle Oluşturma:

ThreadPoolExecutor sınıfının kaynak koduna gittiğimizde 3 constructor(yapıcı) metod olduğu görüyoruz.

corePoolSize: Havuzda tutulacak asgari thread sayısıdır. (allowCoreThreadTimeOut değeri set edilmediği sürece)
maximumPoolSize: Havuzdaki azami thread sayısını belirleyen parametre.
keepAliveTime: corePoolSize değerinin üzerindeki threadlerin ne kadar süre daha havuz içerisinde kalacağını belirleyen parametre.
unit: keepAliveTime değerinin birimini belirleyen parametre
workQueue: Taskların çalıştırılmadan önce tutuldukları queue’yu belirleyen parametre.
handler: Eğer üst sınırı olan bir workQueue ile çalışıyor ve bu queue kapasitesini doldurmuş ise, yeni gelen tasklar geri çevrilir . Handler parametresi ile RejectedExecutionHandler tipinde bir sınıf örneği veririz.

ExecutorService’e İş Atama

ExecutorService, execute(),submit(), invokeAny() ve invokeAll() metodlarıyla Thread çalıştırır.

execute() : Geri dönüş değeri olmayan bir metottur.

submit(): Future türünde sonuç döndürür. 2 parametre alır. İlki Runable nesnesidir, ikincisi ise geri dönüş değeridir. Eğer işlem başarılı olursa Future’ın get() metodu, geri dönüş değeri olarak atadığımız değeri verir. Eğer geri dönüş değerini setlemezsek Future’ın get() metodu null döner.

invokeAny(): Parametre olarak Callable Collection(Collection<? extends Callable<T>>) alır. Başarılı olan bir iş için result döner.

invokeAll(): Parametre olarak Callable Collection(Collection<? extends Callable<T>>) alır. Future koleksiyonu ile tüm işler için sonuç döner.

Not: ExecutorService sınıfı kendiliğinden sonlanmaz. Eğer sonlandırmazsak yeni iş gelene kadar bekleyecektir. ExecutorService’i sonlandırmak için shutdown() ve shutdownNow() metotları mevcuttur.

shutdown(): ExecutorService’i anında değil de, çalışan threadler mevcut işlerini bitirdikten sonra sonlandırır. Ayrıca yeni görevler alınmasını durdurur.

shutdownNow(): ExecutorService’i hemen yok etmeye çalışır.(Hepsi aynı anda bitmeyebilir.).O sırada çalışan işleri liste halinde döndürür.

Bu makaleyi buraya kadar okuduğunuz için teşekkür ederim.

--

--