Herhangi bir uygulamanın birden çok işlemi (örneği) olabilir. Bu işlemlerin her biri tek bir iş parçacığı veya birden çok iş parçacığı olarak atanabilir. Bu eğitimde aynı anda birden fazla görevin nasıl gerçekleştirileceğini göreceğiz ve ayrıca iş parçacıkları ve iş parçacıkları arasındaki senkronizasyon hakkında daha fazlasını öğreneceğiz.
Bu eğitimde şunları öğreneceğiz:
- Tek Konu Nedir
- Java'da Multithreading nedir?
- Java'da İş Parçacığı Yaşam Döngüsü
- Java İş Parçacığı Senkronizasyonu
- Java Çoklu Okuma Örneği
Tek İplik nedir?
Tek bir iş parçacığı temelde hafif ve en küçük işleme birimidir. Java, bir "İş Parçacığı Sınıfı" kullanarak evreleri kullanır.
İki tür iş parçacığı vardır - kullanıcı iş parçacığı ve daemon iş parçacığı (uygulamayı temizlemek istediğimizde ve arka planda kullanıldığımızda daemon evreleri kullanılır).
Bir uygulama ilk başladığında, kullanıcı iş parçacığı oluşturulur. Bunu gönderin, birçok kullanıcı dizisi ve daemon dizisi oluşturabiliriz.
Tek Konu Örneği:
paket demotest;genel sınıf GuruThread{public static void main (String [] args) {System.out.println ("Tek İş Parçacığı");}}
Tek ipliğin avantajları:
- Sistemde tek iş parçacığı yürüttüğü için uygulamadaki ek yükü azaltır
- Ayrıca uygulamanın bakım maliyetini düşürür.
Java'da Multithreading nedir?
Java'da MULTITHREADING , maksimum CPU kullanımı için iki veya daha fazla iş parçacığını aynı anda yürütme işlemidir. Çok iş parçacıklı uygulamalar aynı anda çalışan iki veya daha fazla iş parçacığını yürütür. Bu nedenle, Java'da Eş Zamanlılık olarak da bilinir. Her iplik birbirine paralel ilerler. Çoklu iş parçacıkları ayrı bir bellek alanı tahsis etmezler, dolayısıyla hafızadan tasarruf ederler. Ayrıca, iş parçacıkları arasında bağlam değişimi daha az zaman alır.
Çoklu iş parçacığı örneği:
paket demotest;public class GuruThread1 Runnable'ı uygular{public static void main (String [] args) {Konu guruThread1 = new Thread ("Guru1");Konu guruThread2 = new Thread ("Guru2");guruThread1.start ();guruThread2.start ();System.out.println ("İş parçacığı adları şu şekildedir:");System.out.println (guruThread1.getName ());System.out.println (guruThread2.getName ());}@Overridepublic void run () {}}
Çoklu iş parçacığının avantajları:
- Kullanıcılar, iş parçacıkları bağımsız olduğu için engellenmez ve zaman zaman birden fazla işlem gerçekleştirebiliriz
- Evreler bağımsız olduğundan, bir iş parçacığı bir istisna ile karşılaşırsa diğer evreler etkilenmez.
Java'da İş Parçacığı Yaşam Döngüsü
Bir iş parçacığının Yaşam Döngüsü:
Yukarıdaki diyagramda gösterildiği gibi, ipliğin yaşam döngüsünün çeşitli aşamaları vardır:
- Yeni
- Runnable
- Koşu
- Bekliyorum
- Ölü
- Yeni: Bu aşamada, iş parçacığı "İş Parçacığı sınıfı" sınıfı kullanılarak oluşturulur. Program evreyi başlatana kadar bu durumda kalır . Aynı zamanda doğan iplik olarak da bilinir.
- Runnable: Bu sayfada, iş parçacığı örneği bir başlangıç yöntemiyle çağrılır. İş parçacığı kontrolü, yürütmeyi bitirmesi için programlayıcıya verilir. İş parçacığının çalıştırılıp çalıştırılmayacağı zamanlayıcıya bağlıdır.
- Çalışıyor: İş parçacığı yürütülmeye başladığında, durum "çalışıyor" durumuna değiştirilir. Zamanlayıcı, iş parçacığı havuzundan bir iş parçacığı seçer ve uygulamada çalışmaya başlar.
- Bekliyor: Bu, bir iş parçacığının beklemesi gereken durumdur. Uygulamada birden fazla iş parçacığı çalıştığından, iş parçacıkları arasında senkronizasyona ihtiyaç vardır. Bu nedenle, bir iş parçacığı diğer iş parçacığı çalıştırılıncaya kadar beklemek zorundadır. Bu nedenle bu durum bekleme durumu olarak adlandırılır.
- Ölü: Bu, iş parçacığının sonlandırıldığı durumdur. İş parçacığı çalışır durumdadır ve işlemeyi tamamladığı anda "ölü durumdadır".
İş parçacıkları için yaygın olarak kullanılan yöntemlerden bazıları şunlardır:
Yöntem | Açıklama |
---|---|
Başlat() | Bu yöntem, iş parçacığının yürütülmesini başlatır ve JVM, iş parçacığı üzerinde run () yöntemini çağırır. |
Uyku (milisaniye) | Bu yöntem iş parçacığını uyutur, bu nedenle iş parçacığının yürütülmesi sağlanan milisaniyeler için duraklatılır ve bundan sonra iş parçacığı yeniden çalışmaya başlar. Bu, iş parçacığı senkronizasyonunda yardımcı olur. |
getName () | İpliğin adını döndürür. |
setPriority (int newpriority) | İş parçacığının önceliğini değiştirir. |
Yol ver () | Durma sırasında mevcut iş parçacığının ve diğer iş parçacığının yürütülmesine neden olur. |
Örnek: Bu örnekte, bir iş parçacığı oluşturacağız ve iş parçacıkları için mevcut yerleşik yöntemleri inceleyeceğiz.
paket demotest;public class thread_example1 Runnable {@Overridepublic void run () {}public static void main (String [] args) {Konu guruthread1 = new Thread ();guruthread1.start ();Deneyin {guruthread1.sleep (1000);} catch (InterruptedException e) {// TODO Otomatik oluşturulan yakalama bloğue.printStackTrace ();}guruthread1.setPriority (1);int gurupriority = guruthread1.getPriority ();System.out.println (gurupriority);System.out.println ("İş Parçacığı Çalışıyor");}}
Kodun açıklaması:
- Code Line 2: Runnable arayüzünü uygulayan bir "thread_Example1" sınıfı oluşturuyoruz (bu, örnekleri thread tarafından yürütülmesi amaçlanan herhangi bir sınıf tarafından uygulanmalıdır.)
- Kod Satırı 4: Bu yöntemi geçersiz kılmak zorunlu olduğundan çalıştırılabilir arayüzün çalıştırma yöntemini geçersiz kılar.
- Kod Satırı 6: Burada iş parçacığının yürütülmesine başlayacağımız ana yöntemi tanımladık.
- Kod Satırı 7: Burada yeni bir evre sınıfı başlatarak "guruthread1" olarak yeni bir evre adı oluşturuyoruz.
- Kod Satırı 8: "guruthread1" örneğini kullanarak iş parçacığının "start" yöntemini kullanacağız. Burada iş parçacığı çalışmaya başlayacaktır.
- Kod Satırı 10: Burada "guruthread1" örneğini kullanan iş parçacığının "uyku" yöntemini kullanıyoruz. Bu nedenle, iş parçacığı 1000 milisaniye boyunca uyuyacaktır.
- Kod 9-14: Burada kontrol edilen istisna olduğu için, yani Kesilmiş istisna olduğu için uyku yöntemini try catch bloğuna koyduk.
- Kod Satırı 15: Burada iş parçacığının önceliğini, hangi önceliğe sahip olursa olsun 1'e ayarlıyoruz.
- Kod Satırı 16: Burada getPriority () kullanarak iş parçacığının önceliğini alıyoruz
- Kod Satırı 17: Burada getPriority'den getirilen değeri yazdırıyoruz
- Kod Satırı 18: Burada iş parçacığının çalıştığı bir metin yazıyoruz.
Yukarıdaki kodu çalıştırdığınızda, aşağıdaki çıktıyı alırsınız:
Çıktı:
5, Thread önceliğidir ve Thread Running, kodumuzun çıktısı olan metindir.
Java İş Parçacığı Senkronizasyonu
Çoklu kullanımda, programların asenkron davranışı vardır. Bir iş parçacığı bazı verileri yazıyorsa ve aynı anda veri okuyan başka bir iş parçacığı, uygulamada tutarsızlık yaratabilir.
Paylaşılan kaynaklara iki veya daha fazla iş parçacığı tarafından erişilmesi gerektiğinde, senkronizasyon yaklaşımı kullanılır.
Java, senkronize davranışı uygulamak için senkronize yöntemler sağlamıştır.
Bu yaklaşımda, evre senkronize edilmiş bloğun içine ulaştığında, başka hiçbir evre aynı nesne üzerinde bu yöntemi çağıramaz. Tüm iş parçacıkları, bu iş parçacığı eşitlenmiş bloğu bitirene ve bundan çıkana kadar beklemek zorundadır.
Bu şekilde, senkronizasyon, çok iş parçacıklı bir uygulamada yardımcı olur. Bir iş parçacığı, diğer iş parçacığının yürütülmesini bitirene kadar beklemelidir, ancak diğer iş parçacığının yürütülmesine izin verilir.
Aşağıdaki biçimde yazılabilir:
Eşitlendi (nesne){// Senkronize edilecek ifade bloğu}
Java Çoklu Okuma Örneği
Bu örnekte, iki iş parçacığı alacağız ve iş parçacığının adlarını alacağız.
Örnek 1:
GuruThread1.javapaket demotest;public class GuruThread1, Runnable {/ *** @param args* /public static void main (String [] args) {Konu guruThread1 = new Thread ("Guru1");Konu guruThread2 = new Thread ("Guru2");guruThread1.start ();guruThread2.start ();System.out.println ("İş parçacığı adları şu şekildedir:");System.out.println (guruThread1.getName ());System.out.println (guruThread2.getName ());}@Overridepublic void run () {}}
Kodun açıklaması:
- Kod Satırı 3: Runnable'ı uygulayan bir "GuruThread1" sınıfını aldık (bu, örnekleri evre tarafından yürütülmesi amaçlanan herhangi bir sınıf tarafından uygulanmalıdır.)
- Kod Satırı 8: Bu, sınıfın ana yöntemidir
- Kod Satırı 9: Burada Thread sınıfını başlatıyoruz ve "guruThread1" adında bir örnek oluşturuyoruz ve bir thread oluşturuyoruz.
- Kod Satırı 10: Burada Thread sınıfını başlatıyoruz ve "guruThread2" adlı bir örnek oluşturuyoruz ve bir thread oluşturuyoruz.
- Kod Satırı 11: İş parçacığını başlatıyoruz, yani guruThread1.
- Kod Satırı 12: İş parçacığını, yani guruThread2'yi başlatıyoruz.
- Kod Satırı 13: Metnin çıktısının "Konu adları şu şekildedir:"
- Kod Satırı 14: İş parçacığı sınıfının getName () yöntemini kullanarak 1 iş parçacığının adını alma.
- Kod Satırı 15: İş parçacığı sınıfının getName () yöntemini kullanarak iş parçacığı 2'nin adını alma.
Yukarıdaki kodu çalıştırdığınızda, aşağıdaki çıktıyı alırsınız:
Çıktı:
Konu isimleri burada şu şekilde çıkarılıyor:
- Guru1
- Guru2
Örnek 2:
Bu örnekte, çalıştırılabilir bir arabirimin run () ve start () yöntemlerini geçersiz kılma yöntemlerini öğreneceğiz ve bu sınıftan iki iş parçacığı oluşturup bunları uygun şekilde çalıştıracağız.
Ayrıca iki ders alıyoruz,
- Çalıştırılabilir arayüzü uygulayacak ve
- Ana yönteme sahip olacak ve buna göre uygulanacak bir diğeri.
paket demotest;public class GuruThread2 {public static void main (String [] args) {// TODO Otomatik oluşturulan yöntem saplamasıGuruThread3 threadguru1 = new GuruThread3 ("guru1");threadguru1.start ();GuruThread3 threadguru2 = new GuruThread3 ("guru2");threadguru2.start ();}}class GuruThread3 Runnable {Konu guruthread;özel String guruname;GuruThread3 (Dize adı) {guruname = isim;}@Overridepublic void run () {System.out.println ("İş parçacığı çalışıyor" + guruname);for (int i = 0; i <4; i ++) {System.out.println (i);System.out.println (guruname);Deneyin {Thread.sleep (1000);} catch (InterruptedException e) {System.out.println ("İş parçacığı kesildi");}}}public void başlangıcı () {System.out.println ("İş parçacığı başladı");eğer (guruthread == null) {guruthread = new Thread (bu, guruname);guruthread.start ();}}}
Kodun açıklaması:
- Kod Satırı 2: Burada, içinde ana yöntemin yer alacağı bir "GuruThread2" sınıfını alıyoruz.
- Kod Satırı 4: Burada sınıfın ana yöntemlerinden birini alıyoruz.
- Kod Satırı 6-7: Burada, "threadguru1" olarak GuruThread3 sınıfının (kodun aşağıdaki satırlarında oluşturulan) bir oluşumunu oluşturuyoruz ve iş parçacığını başlatıyoruz.
- Kod Satırı 8-9: Burada GuruThread3 sınıfının (kodun aşağıdaki satırlarında oluşturulan) "threadguru2" olarak başka bir örneğini oluşturuyoruz ve iş parçacığını başlatıyoruz.
- Kod Satırı 11: Burada çalıştırılabilir arabirimi uygulayan bir "GuruThread3" sınıfı oluşturuyoruz (örnekleri evre tarafından yürütülmesi amaçlanan herhangi bir sınıf tarafından uygulanmalıdır.)
- Kod Satırı 13-14: Biri evre tipinde ve diğeri dize sınıfında olan iki sınıf değişkeni alıyoruz.
- Kod Satırı 15-18: guruname sınıf değişkenine atanan ve dolayısıyla iş parçacığının adı saklanan dizge türü (evre adıdır) olarak bir bağımsız değişken alan GuruThread3 yapıcısını geçersiz kılıyoruz.
- Kod Satırı 20: Burada çalıştırılabilir arayüzün run () yöntemini geçersiz kılıyoruz.
- Kod Satırı 21: İş parçacığı adını println deyimini kullanarak çıkarıyoruz.
- Kod Satırı 22-31: Burada sayacı 0'a ilklendirilmiş bir for döngüsü kullanıyoruz ve 4'ten az olmamalıdır (burada herhangi bir sayıyı alabiliriz, bu nedenle döngü 4 kez çalışacaktır) ve sayacı arttırır. İş parçacığı adını yazdırıyoruz ve ayrıca iş parçacığını bir try-catch bloğu içinde 1000 milisaniye boyunca uyku yöntemi kontrol edilen istisnayı artırdığından uyutuyoruz.
- Kod Satırı 33: Burada çalıştırılabilir arayüzün başlangıç yöntemini geçersiz kılıyoruz.
- Kod Satırı 35: "Konu başladı" metnini çıkarıyoruz.
- Kod Satırı 36-40: Burada, sınıf değişkeni guruthread'in içinde bir değer olup olmadığını kontrol etmek için bir if koşulu alıyoruz. Eğer boşsa, adı parametre olarak alan (yapıcıda atanan değer) thread sınıfını kullanarak bir örnek oluşturuyoruz. Bundan sonra iş parçacığı start () yöntemi kullanılarak başlatılır.
Yukarıdaki kodu çalıştırdığınızda aşağıdaki çıktıyı alırsınız:
Çıktı :
İki konu vardır, bu nedenle iki kez "Konu başladı" mesajı alıyoruz.
İplik adlarını çıktı olarak alırız.
Sayacı ve iplik adını yazdırdığımız ve sayacın 0 ile başladığı döngü için devreye girer.
Döngü üç kez yürütülür ve aralarında iş parçacığı 1000 milisaniye boyunca uyur.
Bu nedenle, önce guru1, sonra guru2, sonra tekrar guru2 alıyoruz çünkü iş parçacığı burada 1000 milisaniye uyuyor ve sonra sonraki guru1 ve tekrar guru1, iş parçacığı 1000 milisaniye uyuyor, böylece guru2 ve sonra guru1 alıyoruz.
Özet :
Bu eğitimde, Java'da çok iş parçacıklı uygulamaları ve tek ve çok iş parçacığını nasıl kullanacağımızı gördük.
- Çoklu kullanımda, iş parçacıkları bağımsız olduğundan ve aynı anda birden fazla işlem gerçekleştirebildiğinden kullanıcılar engellenmez
- İpliğin yaşam döngüsünün çeşitli aşamaları,
- Yeni
- Runnable
- Koşu
- Bekliyorum
- Ölü
- Ayrıca uygulamanın sorunsuz çalışmasına yardımcı olan iş parçacıkları arasındaki senkronizasyonu da öğrendik.
- Multithreading, birçok uygulama görevini daha kolay hale getirir.