Şok! İş parçacığını bu şekilde sonlandırmak hizmetin çökmesine neden olur mu?

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 olun

Java 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ı?

Problem 1: Programın bütünlüğünü küçümseyin

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.

İkinci problem: atom mantığını yok edin

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ığını doğru şekilde sonlandırın

İş 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.

  • 1. Çıkış logosunu özelleştirin

    İş 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.

    2. kesinti iş parçacığı sonlandırır

    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.

    sonuç olarak

    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?

    Kız arkadaşım yüksek matematik öğreniyor, onun için bir yığın ile bir hesap makinesi yazmak için 15 dakika harcadım | Güç Projesi
    önceki
    Fuzhou: Kapok sokakları giydiriyor
    Sonraki
    iyi ve kötü günde! Çin, benzeri görülmemiş uluslararası insani acil durum operasyonları başlattı
    Yangzhou, Jiangsu'da yüzden fazla itfaiyeci, kapsamlı acil kurtarma yeteneklerini geliştirmek için yağmurda yarışıyor
    Böyle bir uçuş eğitimi, dövüş gibidir! Havayla savaşmak için açık eğitim, gerçek savaş "barut tadı" dolu
    Kunming sokaklarında komadaki bir genci kurtaran beyazlı genç bayanın hikayesi de efsane.
    Xiaohan Bugün
    Fabrika atölyesinden çıkan sanat grubu, Çin ve Nijerya arasında bir halk kültürü alışverişi köprüsü inşa ediyor
    Bahar Şenliği Taşımacılığı sırasında satılan 300 milyondan fazla bilet, 10. gün tatilden önce yolcu akışının ilk zirvesini kutlayacak.
    Salgının denizaşırı ithalatını kesin olarak önleyin: hem "Doğu Şehri Gücü" hem de "Doğu Şehir Sıcaklığı"
    Microsoft bir kişi için bir şirket mi satın alıyor? Sony programlarını kırmak, hacker romanları yazmak ve sağlam program hayatını izlemek
    iPhone11 fiyatı genel olarak düştü; Haro Travel büyük çaplı işten çıkarmaları reddediyor; LineageOS 17.1 çıktı | Geek Headlines
    4 yılda 46 sürüm, Spring Cloud'un geliştirme geçmişini anlamak için bir makale
    Üflemeyi kes! Python programcıları kayboluyor! Kıdemli CTO: Az önce öğrendiniz mi?
    To Top