Yazar | Pharaoh
Başlamadan önce, aşağıdaki kodda neyin yanlış olduğunu görelim?
public class ThreadStopExample {public static void main (String args) InterruptedException {Thread t1 = new Thread (- > {{System.out.println ("Alt iş parçacığı yürütülmeye başlar"); // İş sürecini simüle et Thread.sleep (1000);} catch (Exception e) {} // Sözde kod: önemli iş yöntemi System.out. println ("Çocuk iş parçacığının önemli iş yöntemleri");}); t1.start; // Alt iş parçacıklarının önce biraz iş çalıştırmasına izin verin Thread.sleep (100); // Alt iş parçacıklarını sonlandır t1.stop; // Bir süre bekleyin, Alt iş parçacığının Thread.sleep (3000); System.out.println ("Ana iş parçacığı yürütmesi tamamlandı");}} olduğundan emin olunJava programlarında izin verilmeyen, iş parçacığını sonlandırmak için yukarıdaki kodun Thread.stop kullandığını keşfetmiş olabilirsiniz. ne? Neden sormuyorsun
Öncelikle IDE sizi küçümseyecek, Thread.stop kullanmanıza engel olacaktır!
ne? Sen inanmıyorsun. O zaman şu resme bakın:
Tamam, peki neden böyle kullanılamıyor? Bana formalite icabı bir sebep vermek zorunda mı?
Aslında böyledir.Kodu makalenin başında alarak çalıştırma sonucu:
Alt iş parçacığı yürütmeye başlar
Ana iş parçacığı yürütme tamamlandı
Aşağıdaki şekilde gösterildiği gibi, büyük bir sorun bulduk, en önemli sözde kod parçası çalıştırılmadı:
İş parçacığını sonlandırmak için durdur'u kullandıktan sonra, iş parçacığının kalan kısmının yürütmeyi bırakacağı görülebilir, bu da ciddi ve zor bir hataya neden olur.İşlenmeyen kod, sistem kaynaklarını serbest bırakan kodsa veya bu program Ana mantık işleme kodu. Bu Programın temel mantığının bütünlüğünü zayıflatarak beklenmedik sorunlara neden olur , Ve çok gizli, bulması ve onarması kolay değil.
Bazı insanlar bunun kolay olmadığını söylüyor, sadece bir nihayet ekledim ve bitti mi?
Bu? ? ? Özellikle bu yıl pek çok kaldıraç var.
Tamam, bu sizi ikna edemeyeceğine göre aşağıya bakalım.
Senkronize etmenin Java'da özel bir evresel kötümser kilit olduğunu biliyoruz. Kodu değiştirmek için kullanırsak, uygun çoklu iş parçacığı iyidir, ancak durdurma yöntemiyle karşılaşırsak, durum böyle değildir, sadece koda bakın.
public class ThreadStopExample {public static void main (String args) InterruptedException {MyThread myThread = new MyThread; Thread t2 = new Thread (myThread); // thread t2.start; for (int i = 0; i < 10; i ++) {Thread t = new Thread (myThread); t.start;} // thread t2.stop'u sonlandır;} / ** * Özel atomik test dizisi * / statik sınıf MyThread, Runnable {// counter int num = 0; @Override public void run {// Atomik işlemlerin senkronize olmasını sağlamak için kod bloklarını senkronize edin (MyThread.class) {// num ++ 'ı artırın; deneyin {// Thread.sleep (100);} catch (InterruptedException e) { e.printStackTrace;} // Azaltım num--; System.out.println (Thread.currentThread.getName + "| num =" + num);}}}}Yukarıdaki programın yürütme sonucu:
Konu-5 | num = 1
Konu-4 | num = 1
Konu-2 | num = 1
Konu-1 | num = 1
Konu-8 | num = 1
Konu-6 | num = 1
Konu-9 | num = 1
Konu-3 | num = 1
Konu-7 | num = 1
Konu-10 | num = 1
Sonuçtan, yukarıdaki kodun senkronize değiştirilmiş ++ ve - işlemlerinden geçtiği ve nihai yazdırılan sonuç numarasının 0 değil 1 olduğu görülebilir.
Bunun nedeni ise Durdurma yöntemi, bu iş parçacığındaki tüm kilitleri serbest bırakarak program yürütme bozukluğuna neden olur ve programın atomik işlem mantığını yok eder.
Yukarıdaki sorunlar JDK'nın durdurma yöntemini terk etmesine neden oldu. Eski kaynak kodu aşağıdaki gibidir:
/ ** * İş parçacığını yürütmeyi durdurmaya zorlar. * < p > * Yüklü bir güvenlik yöneticisi varsa, < kodu > checkAccess < / kod > * yöntem ile çağrılır < kodu > bu < / kod > * argüman olarak. Bu, * ile sonuçlanabilir < kodu > SecurityException < / kod > yükseltilmekte (mevcut iş parçacığında). * < p > * Bu iş parçacığı mevcut iş parçacığından farklıysa (yani, geçerli * iş parçacığı kendisinden başka bir iş parçacığını durdurmaya çalışıyor), * güvenlik yöneticisinin < kodu > checkPermission < / kod > yöntem (* ile < kodu > RuntimePermission ("stopThread") < / kod > argüman) * ek olarak çağrılır. * Yine, bu bir * atılmasına neden olabilir < kodu > SecurityException < / kod > (mevcut ileti dizisinde). * < p > * Bu iş parçacığı tarafından temsil edilen iş parçacığı, anormal olarak yaptığı her şeyi durdurmak ve yeni oluşturulmuş bir * < kodu > ThreadDeath < / kod > bir istisna olarak nesne. * < p > * Henüz başlatılmamış bir iş parçacığını durdurmaya izin verilir. * İş parçacığı sonunda başlatılırsa, hemen sona erer. * < p > * Bir uygulama normalde yakalamaya çalışmamalıdır * < kodu > ThreadDeath < / kod > bazı olağanüstü * temizleme işlemi yapmaması gerekmedikçe (şunu unutmayın: * < kodu > ThreadDeath < / kod > nedenleri < kodu > en sonunda < / kod > * maddeleri < kodu > Deneyin < / kod > iş parçacığı * resmi olarak ölmeden önce yürütülecek ifadeler). < kodu > tutmak < / kod > fıkra bir * yakalar < kodu > ThreadDeath < / kod > nesne, iş parçacığının gerçekten ölmesi için * nesnesini yeniden atmak önemlidir. * < p > * Aksi halde yakalanmamış * istisnalara tepki veren en üst düzey hata işleyici, bir mesaj yazdırmaz veya yakalanmamış istisna bir * örneğiyse * uygulamaya bildirmez. < kodu > ThreadDeath < / kod > . * * @exception SecurityException, eğer mevcut iş parçacığı bu diziyi değiştiremezse * ) * @ see SecurityManager # checkAccess (Thread) * @ see SecurityManager # checkPermission * @deprecated Bu yöntem doğası gereği güvensizdir. * Thread.stop ile bir iş parçacığını durdurmak, onun * kilitlediği tüm monitörlerin kilidini açmasına neden olur (doğal olarak kontrol edilmeyenlerin sonucu * < kodu > ThreadDeath < / kod > Bu monitörler tarafından önceden korunan nesnelerden * herhangi biri * tutarsız bir durumda ise, hasarlı nesneler diğer iş parçacıkları tarafından görünür hale gelir ve potansiyel olarak keyfi davranışlara neden olur. < kodu > Dur < / kod > Hedef iş parçacığının çalışmayı durdurması gerektiğini belirtmek için bazı değişkenleri basitçe * değiştiren kodla değiştirilmelidir. Hedef iş parçacığı bu değişkeni * düzenli olarak kontrol etmeli ve değişken, değişken olduğunu gösteriyorsa düzenli bir şekilde çalıştırma yönteminden dönmelidir. * hedef iş parçacığı uzun süre beklerse (örneğin bir koşul değişkeninde *), < kodu > kesmek < / kod > yöntem, beklemeyi kesmek * için kullanılmalıdır. * Daha fazla bilgi için bkz. * < a href = "{@ docRoot} /../ technotes / guides / concurrency / threadPrimitiveDeprecation.html" > Thread.stop, Thread.suspend ve Thread.resume neden * Kullanımdan Kaldırıldı? < / a > . * / @ Kullanımdan kaldırılmışpublic final void stop {SecurityManager security = System.getSecurityManager; if (security! =) {CheckAccess; if (this! = Thread.currentThread) {security.checkPermission (SecurityConstants.STOP_THREAD_PERMISSION);}} // Sıfır durum değeri "YENİ" e karşılık gelir, kilidi tuttuğumuz için // YENİ değil olarak değiştirilemez. if (threadStatus! = 0) {resume; // Askıya alınmışsa ileti dizisini uyandır; aksi takdirde işlem yok} // VM tüm iş parçacığı durumlarını işleyebilir stop0 (yeni ThreadDeath);}Durdurma yönteminin @Deprecated açıklama ile değiştirildiği ve bu açıklama ile değiştirilen kodun eski bir yöntem olarak temsil edildiği ve kullanılması tavsiye edilmediği görülebilir. Stop ifadelerinden de anlaşılacağı üzere, görevli, güvenli olmayan bir yöntem olduğunu söyleyerek stop kullanımını önermiyor.
İş parçacığı nasıl sonlandırılır? İşte 2 doğru yöntem:
İş parçacığından çıkmak için çıkış bayrağını ayarlayın;
İş parçacığını sonlandırmak için kesme yöntemini kullanın.
İş parçacığından çıkmamız gerekip gerekmediğini belirlemek için bir Boolean değişkenini özelleştirebiliriz, uygulama kodu aşağıdaki gibidir:
// Statik evre sınıfından çıkmak için çıkış bayrağını özelleştirin FlagThread Thread'ı genişletir {public volatile boolean exit = false; public void run {while (! exit) {// Normal iş mantığını gerçekleştir}}}Görülüyor ki, çok iş parçacıklı yürütmenin güvenliğini garanti edebilmek için iş parçacığını değiştirmek için uçucu anahtar sözcüğünü kullandığımız görülüyor İş parçacığının çıkmasına izin vermemiz gerektiğinde, yalnızca değişken çıkışını true olarak atamamız gerekir.
Interrupt yöntemini kullandığımızda yukarıdaki iki örneğin yürütme sonuçları normaldir ve yürütme kodu aşağıdaki gibidir:
public class ThreadStopExample {public static void main (String args) InterruptedException atıyor {// Problem 1: Programın bütünlüğü yok edildi Thread t1 = new Thread (- > {deneyin {System.out.println ("Alt iş parçacığı yürütülmeye başlar"); // İş sürecini simüle et Thread.sleep (1000);} catch (Exception e) {} // Sözde kod: önemli iş yöntemi System.out.println ("Alt iş parçacığı için önemli iş yöntemleri");}); t1.start; // Alt iş parçacığının önce biraz iş çalıştırmasına izin verin Thread.sleep (100); // Alt iş parçacığını sonlandır t1.interrupt; // Bir süre bekleyin, emin olun Alt evre "Thread.sleep (3000); System.out.println (" ana iş parçacığı yürütme tamamlandı ")" yürütür "; // Problem 2: Atomik mantık yok edildi MyThread myThread = new MyThread; Thread t2 = new Thread (myThread); // Thread t2.start; for (int i = 0; i < 10; i ++) {Thread t = new Thread (myThread); t.start;} // Thread t2.interrupt sonlandır;} / ** * Özel atomik test dizisi * / statik sınıf MyThread, Runnable {// counter int num = 0; @Override public void run {// Atomik işlemlerin senkronize olmasını sağlamak için kod bloklarını senkronize edin (MyThread.class) {// num ++ 'ı artırın; deneyin {// Thread.sleep (100);} catch (InterruptedException e) { System.out.println (e.getMessage);} // Azaltım numarası--; System.out.println (Thread.currentThread.getName + "| num =" + num);}}}}Yukarıdaki programın yürütme sonucu:
Alt iş parçacığı yürütmeye başlar
Alt iş parçacığı için önemli iş yöntemleri
Ana iş parçacığı yürütme tamamlandı
uyku kesildi
Konu-1 | num = 0
Konu-9 | num = 0
Konu-10 | num = 0
Konu-7 | num = 0
Konu-6 | num = 0
Konu-5 | num = 0
Konu-4 | num = 0
Konu-2 | num = 0
Konu-3 | num = 0
Konu-11 | num = 0
Konu-8 | num = 0
Yukarıdaki uygulamanın beklentilerimizi karşıladığı görülebilir, bu iş parçacığını sonlandırmanın doğru yoludur.
Bu makalede, iş parçacıklarını sonlandırmanın üç yolundan, çıkış bayrağını özelleştirmenin yolundan, durdurma yönteminden veya kesmenin yolundan bahsettik. Bunlar arasında durdurma yöntemi, programın bütünlüğünün ve atomikliğinin yok olmasına neden olacak ve bu yöntem JDK tarafından süresi dolmuş bir yöntem olarak tanımlanmakta ve önerilmemektedir.Kesme yöntemi şüphesiz iş parçacığı sonlandırmamız için en uygun yoldur.
"Bir milyon insan yapay zekayı öğreniyor" un önemli bir parçası olarak, 2020 AIProCon Geliştirici Konferansı Olacak 26 Haziran Çevrimiçi canlı yayın aracılığıyla geliştiriciler, mevcut AI'nın en son teknoloji araştırması, temel teknolojisi ve uygulaması ve iş vakalarının pratik deneyimi hakkında tek durakta bilgi edinebilir ve ayrıca harika ve çeşitli geliştirici salonlarına ve programlama projelerine çevrimiçi olarak katılabilir. Bir dizi ileriye dönük aktiviteye ve çevrimiçi canlı yayın etkileşimlerine katılın. Yalnızca on binlerce geliştiriciyle iletişim kurmakla kalmaz, aynı zamanda özel canlı yayın hediyeleri kazanma ve teknik uzmanlarla bağlantı kurma fırsatına da sahip olursunuz.
Yorum alanında seçilirseniz, 299 yuan değerinde "2020 AI Geliştiriciler Konferansı" için çevrimiçi canlı bir bilet alacaksınız. Parmaklarınızı hareket ettirin ve söylemek istediklerinizi yazın
Huawei, AI Dragon Ball'u topladı, "Summon Dragon" çok uzakta değil
Çin insansız hava aracı "Old Paoer" ın anıları
Jingdong Mall'un arkasındaki yapay zeka teknolojisinin sırrı - anahtar kelimelere dayalı otomatik özet oluşturma
İnternetin babası yeni tacı teşhis etti, bir efsane: Google'ın başkan yardımcısı ve NASA'da misafir bilim insanı olarak görev yaptı
Hiç bu kadar kolay olmamıştı: Kafka'ya karşı saldırmanız için sizi 10 dakika alacak!
Programcılar kodun olmadığı bir çağda işlerini nasıl koruyabilirler?