Jadual Kandungan
Misteri Thread.stop being disabled
Bagaimanakah cara untuk menamatkan benang dengan selamat?
捕获异常之后的处理
Rumah Java javaTutorial Bagaimana untuk menamatkan benang di Jawa

Bagaimana untuk menamatkan benang di Jawa

Apr 26, 2023 am 08:58 AM
java

Misteri Thread.stop being disabled

Ditanya cara menamatkan thread, mungkin kebanyakan orang tahu bahawa anda boleh memanggil kaedah Thread.stop.

Tetapi kaedah ini tidak lagi disyorkan selepas jdk1.2. Mengapa ia tidak disyorkan?

Mari kita lihat dulu definisi kaedah ini:

  @Deprecated(since="1.2")
    public final void stop() {
        @SuppressWarnings("removal")
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            checkAccess();
            if (this != Thread.currentThread()) {
                security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
            }
        }
        // A zero status value corresponds to "NEW", it can't change to
        // not-NEW because we hold the lock.
        if (threadStatus != 0) {
            resume(); // Wake up thread if it was suspended; no-op otherwise
        }

        // The VM can handle all thread states
        stop0(new ThreadDeath());
    }
Salin selepas log masuk

Daripada kod tersebut, kita dapat melihat bahawa kaedah henti terlebih dahulu menyemak sama ada terdapat kebenaran capaian benang. Jika anda mempunyai kebenaran, tentukan sama ada utas semasa ialah utas yang baru dibuat. Jika tidak, maka hubungi kaedah resume untuk melepaskan keadaan yang digantung.

Akhirnya panggil kaedah stop0 untuk menamatkan urutan.

Antaranya, resume dan stop0 adalah dua kaedah asli, dan pelaksanaan khusus tidak akan dibincangkan di sini.

Nampaknya kaedah berhenti itu munasabah dan tiada masalah. Jadi mengapa kaedah ini tidak selamat?

Seterusnya mari kita lihat contoh.

Kami mencipta kelas NumberCounter Kelas ini mempunyai kaedah peningkatanNumber yang selamat, yang digunakan untuk menambah satu pada nombor:

public class NumberCounter {
    //要保存的数字
    private volatile int number=0;
    //数字计数器的逻辑是否完整
    private volatile boolean flag = false;

    public synchronized int increaseNumber() throws InterruptedException {
        if(flag){
            //逻辑不完整
            throw new RuntimeException("逻辑不完整,数字计数器未执行完毕");
        }
        //开始执行逻辑
        flag = true;
        //do something
        Thread.sleep(5000);
        number++;
        //执行完毕
        flag=false;
        return number;
    }
}
Salin selepas log masuk

Malah, dalam kerja sebenar, kaedah sedemikian mungkin. diperlukan Ia mengambil masa yang lama untuk dilaksanakan, jadi di sini kami mensimulasikan operasi yang memakan masa ini dengan memanggil Thread.sleep.

Di sini kami juga mempunyai parameter bendera untuk menandakan sama ada kaedah increaseNumber telah berjaya dilaksanakan.

Baiklah, seterusnya kita panggil kaedah kelas ini dalam utas dan lihat apa yang berlaku:

    public static void main(String[] args) throws InterruptedException {
        NumberCounter numberCounter= new NumberCounter();
        Thread thread = new Thread(()->{
            while (true){
                try {
                    numberCounter.increaseNumber();
                } catch (InterruptedException e) {
                   e.printStackTrace();
                }
            }
        });
        thread.start();
        Thread.sleep(3000);
        thread.stop();
        numberCounter.increaseNumber();
    }
Salin selepas log masuk

Di sini, kami mencipta utas dan tunggu sehingga utas ini berjalan 3 Saat kemudian, kaedah thread.stop dipanggil terus dan kami mendapati pengecualian berikut:

Pengecualian dalam thread "main" java.lang.RuntimeException: Logik tidak lengkap dan pembilang digital belum dilaksanakan.
di com.flydean.NumberCounter.increaseNumber(NumberCounter.java:12)
di com.flydean.Main.main(Main.java:18)

Ini kerana benang. Kaedah berhenti secara langsung menamatkan larian benang, menyebabkan mberCounter.increaseNumber tidak dapat diselesaikan.

Tetapi keadaan belum selesai ini disembunyikan Jika anda menggunakan kaedah thread.stop untuk menamatkan thread, ia berkemungkinan membawa kepada hasil yang tidak diketahui.

Jadi, kami katakan thread.stop tidak selamat.

Bagaimanakah cara untuk menamatkan benang dengan selamat?

Jadi, jika kaedah thread.stop tidak dipanggil, bagaimanakah kita boleh menamatkan benang dengan selamat?

Keselamatan yang dipanggil bermakna logik dalam benang perlu dilaksanakan sepenuhnya, bukan separuh dilaksanakan.

Untuk mencapai kesan ini, Thread memberikan kita tiga kaedah yang serupa, iaitu interrupted, interrupted dan isInterrupted.

interrupted adalah untuk menetapkan bendera interrupted untuk thread yang terganggu adalah untuk mengesan gangguan dan mengosongkan status interrupted hanya mengesan gangguan; Satu lagi perkara penting ialah interrupted ialah kaedah kelas yang bertindak pada thread semasa dan isInterrupted bertindak pada thread ini, iaitu, thread yang diwakili oleh contoh yang memanggil kaedah ini dalam kod.

gangguan ialah kaedah gangguan adalah seperti berikut:

  • Jika contoh urutan semasa memanggil tunggu(), tunggu(lama) atau tunggu( lama, kaedah int) atau kaedah join(), join(long), join(panjang, int) atau kaedah Thread.sleep(panjang) atau Thread.sleep(panjang, int) dipanggil dalam kejadian ini dan sedang menyekat keadaan, statusnya yang terganggu akan dikosongkan dan InterruptedException akan diterima.

  • Jika urutan ini disekat semasa operasi I/O pada InterruptibleChannel, saluran akan ditutup, status gangguan urutan akan ditetapkan kepada benar dan utas A java.nio .channels.ClosedByInterruptException pengecualian akan diterima.

  • Jika urutan ini disekat dalam java.nio.channels.Selector, status gangguan urutan akan ditetapkan kepada benar dan ia akan kembali serta-merta daripada operasi pilih .

  • Jika tiada syarat di atas adalah benar, tetapkan status gangguan kepada benar.

Dalam contoh di atas, dalam kaedah increaseNumber NumberCounter, kami memanggil kaedah Thread.sleep, jadi jika kaedah interrupt thread dipanggil pada masa ini, thread akan membuang An InterruptedException.

Mari tukar contoh panggilan di atas kepada yang berikut:

    public static void main(String[] args) throws InterruptedException {
        NumberCounter numberCounter = new NumberCounter();

        Thread thread = new Thread(() -> {
            while (true) {
                try {
                    numberCounter.increaseNumber();
                } catch (InterruptedException e) {
                    System.out.println("捕获InterruptedException");
                    throw new RuntimeException(e);
                }
            }
        });

        thread.start();
        Thread.sleep(500);
        thread.interrupt();
        numberCounter.increaseNumber();
    }
Salin selepas log masuk

Cuba lagi selepas berjalan:

Exception in thread "main" Exception in thread "Thread-0" java.lang.RuntimeException: 逻辑不完整,数字计数器未执行完毕
at com.flydean.NumberCounter.increaseNumber(NumberCounter.java:12)
at com.flydean.Main2.main(Main2.java:21)
java.lang.RuntimeException: java.lang.thread.interrupt: sleep interrupted
at com.flydean.Main2.lambda$main$0(Main2.java:13)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.InterruptedException: sleep interrupted
at java.base/java.lang.Thread.sleep(Native Method)
at com.flydean.NumberCounter.increaseNumber(NumberCounter.java:17)
at com.flydean.Main2.lambda$main$0(Main2.java:10)
... 1 more
捕获InterruptedException

可以看到,我们捕获到了这个InterruptedException,并且得知具体的原因是sleep interrupted。

捕获异常之后的处理

从上面的分析可以得知,thread.stop跟thread.interrupt的表现机制是不一样的。thread.stop属于悄悄终止,我们程序不知道,所以会导致数据不一致,从而产生一些未知的异常。

而thread.interrupt会显示的抛出InterruptedException,当我们捕捉到这个异常的时候,我们就知道线程里面的逻辑在执行的过程中受到了外部作用的干扰,那么我们就可以执行一些数据恢复或者数据校验的动作。

在上面的代码中,我们是捕获到了这个异常,打印出异常日志,然后向上抛出一个RuntimeException。

正常情况下我们是需要在捕获异常之后,进行一些处理。

那么自己处理完这个异常之后,是不是就完美了呢?

答案是否定的。

因为如果我们自己处理了这个InterruptedException, 那么程序中其他部分如果有依赖这个InterruptedException的话,就可能会出现数据不一致的情况。

所以我们在自己处理完InterruptedException之后,还需要再次抛出这个异常。

怎么抛出InterruptedException异常呢?

有两种方式,第一种就是在调用Thread.interrupted()清除了中断标志之后立即抛出:

   if (Thread.interrupted())  // Clears interrupted status!
       throw new InterruptedException();
Salin selepas log masuk

还有一种方式就是,在捕获异常之后,调用Thread.currentThread().interrupt()再次中断线程。

public void run () {
  try {
    while (true) {
      // do stuff
    }
  }catch (InterruptedException e) {
    LOGGER.log(Level.WARN, "Interrupted!", e);
    // Restore interrupted state...
    Thread.currentThread().interrupt();
  }
}
Salin selepas log masuk

这两种方式都能达到预想的效果。

Atas ialah kandungan terperinci Bagaimana untuk menamatkan benang di Jawa. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Tetapan grafik terbaik
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Cara Memperbaiki Audio Jika anda tidak dapat mendengar sesiapa
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Cara Membuka Segala -galanya Di Myrise
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Akar Kuasa Dua di Jawa Akar Kuasa Dua di Jawa Aug 30, 2024 pm 04:26 PM

Panduan untuk Square Root di Java. Di sini kita membincangkan cara Square Root berfungsi di Java dengan contoh dan pelaksanaan kodnya masing-masing.

Nombor Sempurna di Jawa Nombor Sempurna di Jawa Aug 30, 2024 pm 04:28 PM

Panduan Nombor Sempurna di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor Perfect dalam Java?, contoh dengan pelaksanaan kod.

Nombor Armstrong di Jawa Nombor Armstrong di Jawa Aug 30, 2024 pm 04:26 PM

Panduan untuk Nombor Armstrong di Jawa. Di sini kita membincangkan pengenalan kepada nombor Armstrong di java bersama-sama dengan beberapa kod.

Penjana Nombor Rawak di Jawa Penjana Nombor Rawak di Jawa Aug 30, 2024 pm 04:27 PM

Panduan untuk Penjana Nombor Rawak di Jawa. Di sini kita membincangkan Fungsi dalam Java dengan contoh dan dua Penjana berbeza dengan contoh lain.

Weka di Jawa Weka di Jawa Aug 30, 2024 pm 04:28 PM

Panduan untuk Weka di Jawa. Di sini kita membincangkan Pengenalan, cara menggunakan weka java, jenis platform, dan kelebihan dengan contoh.

Nombor Smith di Jawa Nombor Smith di Jawa Aug 30, 2024 pm 04:28 PM

Panduan untuk Nombor Smith di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor smith di Jawa? contoh dengan pelaksanaan kod.

Soalan Temuduga Java Spring Soalan Temuduga Java Spring Aug 30, 2024 pm 04:29 PM

Dalam artikel ini, kami telah menyimpan Soalan Temuduga Spring Java yang paling banyak ditanya dengan jawapan terperinci mereka. Supaya anda boleh memecahkan temuduga.

Cuti atau kembali dari Java 8 Stream Foreach? Cuti atau kembali dari Java 8 Stream Foreach? Feb 07, 2025 pm 12:09 PM

Java 8 memperkenalkan API Stream, menyediakan cara yang kuat dan ekspresif untuk memproses koleksi data. Walau bagaimanapun, soalan biasa apabila menggunakan aliran adalah: bagaimana untuk memecahkan atau kembali dari operasi foreach? Gelung tradisional membolehkan gangguan awal atau pulangan, tetapi kaedah Foreach Stream tidak menyokong secara langsung kaedah ini. Artikel ini akan menerangkan sebab -sebab dan meneroka kaedah alternatif untuk melaksanakan penamatan pramatang dalam sistem pemprosesan aliran. Bacaan Lanjut: Penambahbaikan API Java Stream Memahami aliran aliran Kaedah Foreach adalah operasi terminal yang melakukan satu operasi pada setiap elemen dalam aliran. Niat reka bentuknya adalah

See all articles