Thread Nedir ve Nasıl Tanımlanır
Thread (İş Parçası)
Thread kelimesi türkçeye iş parçası olarak çevrilmiştir. İş yapan parça. Bu tanım üzerinden devam ettiğimizde Multi-thread in karşılığıda birden fazla iş parçaları olur.
Bu genel tanımdan sonra, Java programlama dili içerisinde thread kavramını incelemeye çalışalım.
Bir java uygulaması, varsayılan olarak birim zamanda tek bir iş yapacaktır. Bu ana iş parçası Main Thread olarak adlandırılır. Bir iş parçası içerisinde çağrılan tüm metotlar birbirlerinin bitişini beklemek zorundadır. Yani akış ardışıkdır. Bu ardışık mantık ve tek thread bazı durumlarda uygulama geliştirmemizi kısıtlar veya yetersiz performansa sebebiyet verir.
Bu durumları tek bir örnek üzerinden incelemeye çalışalım. Bunun için;
Soket aracılığı ile başka bir uygulamaya bağlanan, veri alan ve aldığı verileri işleyen bir uygulama yapmakta olduğumuzu düşünelim. Sadece ana iş parcasının olduğu bir uygulama bizim için uygun olmayacaktır.
- Çünkü uygulama, verilen bilgiler ile bir sunucu uygulamaya bağlanacak ve soketi dinleyecektir. Sırası ile aşağıdaki gibi ilerleyen bir metot da;
bilgileriAl();
sunucuyaBaglanVeriBekle();
ekranıCiz();
.
.
.
uygulama sunucuyaBaglanVeriBekle() metodundan sonra devam etmez. Çünkü bu metot yaptığı iş gereği uygulama çalıştığı sürece, sonlanmaması gereken bir metoddur. Sokete bağlan işini bir başka thread’in yapması gerekir. - Soketten veri alındığı zaman, alınan bu veri üzerinde bazı işlemlerin yapılması gerekecektir. İşlemler yürütülürken, sunucu tarafından gönderilen yeni veriler alınamayacaktır. Verilerin işlenmesi işini başka bir thread’e yaptırabiliriz. Bu sayede sunucu tarafında veri yığılması engellenir. Uygulamamızın cevap verme süresi kısalır. Veri işleme işini bir den fazla thread’e yaptırdığımız durumda da uygulamamızın performansı artar.
Bu ve benzeri örnekler thread kullanmamız gereken durumları göstermektedir.
Bu faydaları yanında thread kullanımının bazı sakıncaları da mevcuttur. Bu sebeple yazılımcıya düşen, optimum noktayı bulabilmektir.
- Fazla sayıda thread kullanmamız uygulamayı karmaşık hale getirebilir.
- Thread’lerin kullandığı paylaşımlı veriler, sınıf örnekleri olabilir ve bunlara çok dikkat edilmesi gerekir.
- Thread’ler kendi local stacklerine sahiptir. Fazla sayıda thread daha fazla memory demektir. Out of Memory hatası alma ihtimalimiz artar.
- Fazla sayıda thread CPU switch işlemine ve performans kaybına sebep olur.
Bu girişten sonra thread tanımlamaya geçebiliriz.
Thread Tanımlama
Java’da thread tanımlamak için Thread sınıfını kullanırız. Bu sınıf java.lang paketinin altındadır.
Thread tanımı;
1 2 3 4 5 6 7 8 9 10 11 12 |
package io.bilisim.java.thread.main; public class AppStarter { public static void main(String[] args) { Thread firstThread = new Thread(); firstThread.start(); } } |
Bu şekilde bir thread tanımlamış olduk. Ama thread tarafından çalıştırılacak herhangi bir kod belirtmedik. Kod belirtme işlemini iki temel yol ile yapabiliriz.
- Thread sınıfının bir alt sınıfı ile. Yani Thread sınıfını extend eden bir sınıf oluştururuz ve run metodunu override ederiz.Böylece thread tarafından çalıştırılacak kodu belirtebiliriz. Bu işlemi Thread sınıfının anonim sınıfını oluşturarakta yapabiliriz. Her iki yöntem için örneklerimiz şu şekilde;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package io.bilisim.java.thread.subclass; public class ThreadSubClass extends Thread{ @Override public void run() { System.out.println("Merhaba Thread Sub Class"); } } |
Şimdi main metotu yazalım.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package io.bilisim.java.thread.main; import io.bilisim.java.thread.subclass.ThreadSubClass; public class AppStarter { public static void main(String[] args) { Thread thread = new Thread(new ThreadSubClass()); thread.start(); } } |
Kodumuzu çalıştırıdığımız da Merhaba Thread çıktısını almış olmamız lazım. İlk thread tanımımızdan farklı olarak, Thread yapılandırıcısına Thread sınıfı extend edip, run metodunu override eden ThreadSubClass sınıfımızın bir instance ini gönderdik. Böylece istediğimiz kod run metodu içinde çalıştı.
Anonim sınıf olarak ise Thread şu şekilde oluşturulur:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package io.bilisim.java.thread.main; public class AppStarter { public static void main(String[] args) { Thread thread = new Thread(){ @Override public void run() { System.out.println("Merhaba Anonim Thread"); } }; thread.start(); } } |
Programın çıktısı Merhaba Anonim Thread olucaktır.
- Runnable interface’ini implemente ederek thread oluşturabiliriz. Alt sınıf oluşturduğumuz örnekten tek farkı Thread sınıfı extend edilmez, Runnable interface’i implement edilir.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package io.bilisim.java.thread.runnable; public class RunnableClass implements Runnable{ @Override public void run() { System.out.println("Merhaba Runnable Thread"); } } |
Ana metodumuz:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package io.bilisim.java.thread.main; import io.bilisim.java.thread.runnable.RunnableClass; public class AppStarter { public static void main(String[] args) { Thread thread = new Thread(new RunnableClass()); thread.start(); } } |
Program çıktımızda Merhaba Runnable Thread olacaktır.
Thread oluştururken hem Thread sınıfının alt sınıfından hem de runnable interface implementasyonundan oluşturabiliriz. Genel yaklaşım Runnable implementasyonunun tercih edilmesi şeklindedir. Çünkü java da sadece tek bir sınıf extend edebiliriz ama birden fazla interface implemente edebiliriz. O yüzden interface bize daha fazla esneklik sağlar.
Thread başlatırken çok dikkat etmemiz gereken nokta, start() metodunu kullanmaktır. Thread i run metodunu çağırarakta başlatabiliriz. Ama bu durumda main thread akışı durur. Thread kodunun yönetilmesini ana iş parçası yapar. Bu sebeple thread başlatırken start metodunu kullanmalıyız.
Aşağıdaki örneğimizde thread’i hem start hem de run metotları ile başlatıp, uygulama çıktılarını inceleyelim.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package io.bilisim.java.thread.runnable; import java.util.Calendar; public class RunnableClass implements Runnable{ @Override public void run() { System.out.println("Merhaba Runnable Thread. Time: "+Calendar.getInstance().get(Calendar.SECOND)); try { Thread.sleep(2000); } catch (Exception e) { e.printStackTrace(); } } } |
Metot içerisine 2 saniyelik bekleme ekledik. Main metodumuz şu şekilde olacak:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package io.bilisim.java.thread.main; import java.util.Calendar; import io.bilisim.java.thread.runnable.RunnableClass; public class AppStarter1 { public static void main(String[] args) { Thread thread = new Thread(new RunnableClass()); thread.start(); System.out.println("Main Thread. Time: "+Calendar.getInstance().get(Calendar.SECOND)); } } |
main metot içerisinde start ile threadimizi başlattık. Uygulamanın çıktısı aşağıdaki gibi olacak:
1 2 3 4 5 6 |
Main Thread. Time: 34 Merhaba Runnable Thread. Time: 34 |
Gördüğümüz gibi, main thread akışı herhangi bir kesintiye uğramadı. Şimdi aynı metot içinde thread’imizi run metodu ile çalıştıralım.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package io.bilisim.java.thread.main; import java.util.Calendar; import io.bilisim.java.thread.runnable.RunnableClass; public class AppStarter2 { public static void main(String[] args) { Thread thread = new Thread(new RunnableClass()); thread.run(); System.out.println("Main Thread. Time: "+Calendar.getInstance().get(Calendar.SECOND)); } } |
Çıktı:
1 2 3 4 5 6 |
Merhaba Runnable Thread. Time: 19 Main Thread. Time: 21 |
Görüğümüz gibi, thread run ile çalıştırıldığında, main thread orada duraksadı ve thread’in metodu bitinceye kadar bekledi. O yüzden start metodunu kullanmaya dikkat edelim.
Thread İsimlendirme
Oluşturduğumuz threadlere isim verebiliriz. İsim vermek thread’leri izleyebilmemizi kolaylaştırır. Thread sınıfı, sınıf instance degeri ile beraber thread isminide alan bir yapılandırıcı sunar. Bunun yanında setName() metodunu çağırarak da isim verebiliriz. Her iki yöntem için örneklerimiz aşağıdadır.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package io.bilisim.java.thread.main; import io.bilisim.java.thread.runnable.RunnableClass; public class AppStarter3 { public static void main(String[] args) { Thread thread = new Thread(new RunnableClass(),"Runnable Class"); thread.start(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package io.bilisim.java.thread.main; import io.bilisim.java.thread.runnable.RunnableClass; public class AppStarter4 { public static void main(String[] args) { Thread thread = new Thread(new RunnableClass()); thread.setName("Runnable Class"); thread.start(); } } |
Bu makalemizde, java ile thread konusuna giriş yaptık.
Şimdilik bu kadar. İnşallah faydalı olmuştur.
İyi Çalışmalar