Rumah  >  Artikel  >  Java  >  Pengenalan terperinci kepada gangguan benang di Jawa

Pengenalan terperinci kepada gangguan benang di Jawa

WBOY
WBOYke hadapan
2022-11-09 13:56:441205semak imbas

Artikel ini membawakan anda pengetahuan yang berkaitan tentang java, yang terutamanya memperkenalkan kandungan yang berkaitan tentang gangguan benang ialah cara untuk mengganggu antara satu sama lain, seperti dua Terdapat utas a dan b a mahu mengganggu perlaksanaan b pada masa tertentu, ia boleh memanggil kaedah b.interrupt() untuk mencelah. Mari kita lihat bersama-sama.

Pengenalan terperinci kepada gangguan benang di Jawa

Kajian yang disyorkan: "tutorial video java"

Gangguan benang dalam Java

Kaedah berkaitan gangguan 1 Pengenalan

Kaedah interrupt(), kaedah isInterrupted() dan kaedah interrupted() dalam pengaturcaraan berbilang benang Java adalah semua kaedah yang berkaitan dengan gangguan benang, dan semuanya sangat penting. Nama ketiga-tiga kaedah ini sangat serupa, dan mudah untuk mengelirukan jika anda tidak memahami prinsipnya. Ia diperkenalkan di sini untuk membezakannya. Memandangkan kaedah interrupt() dan kaedah isInterrupted() ialah kedua-dua kaedah contoh (kaedah statik bukan kelas), saya menambah thread1 di hadapan untuk menunjukkan utas instantiated tertentu:

benang1. kaedah interrupt()

thread1.interrupt() kaedah digunakan untuk mengganggu urutan. Contohnya, terdapat dua utas 打断 dan a Apabila utas b mahu mengganggu utas a atas sebab tertentu, b boleh memanggil a secara dalaman. Walau bagaimanapun, sila ambil perhatian bahawa pelaksanaan dicapai dengan menetapkan b.interrupt() urutan b. Semasa pelaksanaan kod benang 中断状态标记, b boleh dinilai secara berterusan dalam badan gelung untuk mengesahkan sama ada ia sebenarnya bertindak balas kepada permintaan gangguan 中断状态标记 (seperti keluar dari pelaksanaan, dsb.). Kaedah a

benang1.isInterrupted() kaedah

digunakan untuk mendapatkan status gangguan bagi utas. Contohnya, terdapat dua utas thread1.isInterrupted() dan a Apabila utas b mahu mengganggu utas a atas sebab tertentu, ia boleh mengganggu b melalui b.interrupt(). Di dalam rangkaian b, anda boleh menentukan status gangguannya dan sama ada ia terganggu, dan kemudian mengesahkan sama ada hendak membalas permintaan gangguan berdasarkan status gangguan (seperti keluar dari badan gelung urutan semasa, dsb.). Kaedah b dipanggil terus dalam kaedah thread1.isInterrupted() Parameter native masuk ialah ClearInterrupted, yang bermaksud bendera status gangguan tidak dikosongkan: false

public boolean isInterrupted() {
  return isInterrupted(false);
}// ClearInterrupted表示是否清楚中断状态标记private native boolean isInterrupted(boolean ClearInterrupted);
Oleh itu, selepas memanggil. kaedahnya, bit bendera gangguan tidak dikosongkan.

Kaedah Thread.interrupted()

ialah kaedah statik yang ditakrifkan pada kelas Thread.interrupted(), digunakan untuk menentukan Thread semasa benang Status gangguan . Melihat pada kod sumber kelas , anda dapat melihat bahawa pelaksanaan kaedah thread1.isInterrupted() adalah sangat mudah Kaedah dipanggil secara terus secara dalaman, tetapi parameter melepasi Thread, yang mana. bermakna mengosongkan tanda status gangguan: Thread.interrupted()nativeClearInterruptedtrueIa boleh dilihat bahawa perbezaan antara

dan
public static boolean interrupted() {
  return currentThread().isInterrupted(true);
}// ClearInterrupted表示是否清楚中断状态标记private native boolean isInterrupted(boolean ClearInterrupted);
sebenarnya terletak pada sama ada untuk menetapkan semula selepas mendapatkan bendera status gangguan. Anda boleh memilih untuk menggunakannya mengikut keperluan anda.

thread1.isInterrupted()2 Cara memberhentikan benang dengan anggun tanpa mempertimbangkan penyekatan benang Thread.interrupted()Untuk menghentikan larian benang dengan anggun, anda memerlukan mekanisme gangguan yang diperkenalkan sebelum ini. Sebagai contoh, terdapat dua utas

dan

Apabila utas

mahu mengganggu utas

, ia boleh menetapkan bendera gangguan bagi utas a dengan memanggil kaedah b untuk memberitahu utas <.> tujuan. Urutan a perlu sentiasa menyemak tanda sampukannya sendiri untuk bertindak balas kepada sampukan daripada rangkaian lain pada bila-bila masa, seperti yang ditunjukkan dalam pelaksanaan berikut: bb.interrupt()bDi sini urutan baharu dicipta dalam b b, benang

secara dalaman adalah badan gelung Pada permulaan setiap gelung, status gangguan diperiksa untuk mengesahkan sama ada ia telah diganggu, ia akan keluar dari gelung dan menamatkan pelaksanaan benang. Benang utama tidur selama 1ms dan biarkan benang b gelung beberapa kali dahulu. Kemudian utas utama mengganggu utas
public class TestMain {
    public static void main(String[] args) throws InterruptedException {
        Thread b = new Thread(new Runnable() {
            @Override
            public void run() {
                int num = 0;
                while(true) {
                    if (Thread.interrupted()) {
                        break;
                    }
                    System.out.println("thread b running, num is:" + num++);
                }
            }
        });
        b.start();
        // 主线程sleep 1ms,让线程b循环一小会
        Thread.sleep(1);
        // 中断线程b
        b.interrupt();
    }
}
melalui

. Apabila anda menjalankan program, anda boleh melihat output berikut (hasilnya berbeza pada mesin yang berbeza): 主线程

thread b running, num is:0thread b running, num is:1thread b running, num is:2...
thread b running, num is:25thread b running, num is:26thread b running, num is:27Process finished with exit code 0

可以看到主线程成功的中断了线程b。当然,主线程之所以能成功的中断线程b,是因为线程b一直在检查自己的中断状态(如果线程b太自我,不考虑其他线程,只考虑自己运行,那主线程就无法成功打断线程b了)。

3 考虑线程阻塞时如何优雅的停止一个线程

前面我们成功的在主线程中中断了线程b,然后如果线程b中存在阻塞,比如下面的代码所示,线程b在sleep时被主线程中断:

public class TestMain {
    public static void main(String[] args) throws InterruptedException {
        Thread b = new Thread(new Runnable() {
            @Override
            public void run() {
                int num = 0;
                while(true) {
                    if (Thread.interrupted()) {
                        break;
                    }
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // Thread.currentThread().interrupt();
                        e.printStackTrace();
                    }
                    System.out.println("thread b running, num is:" + num++);
                }
            }
        });
        b.start();
        // 主线程sleep5.5秒,让线程b循环5次
        Thread.sleep(5500);
        // 中断线程b
        b.interrupt();
    }
}

这时线程b会抛出InterruptedException异常,上面的代码中我们仅仅打印了下该异常,相当于什么都没做。运行该代码结果如下:

thread b running, num is:0thread b running, num is:1thread b running, num is:2thread b running, num is:3thread b running, num is:4java.lang.InterruptedException: sleep interrupted
  at java.lang.Thread.sleep(Native Method)
  at test.TestMain$1.run(TestMain.java:25)
  at java.lang.Thread.run(Thread.java:748)
thread b running, num is:5thread b running, num is:6thread b running, num is:7thread b running, num is:8thread b running, num is:9...

可以看出,主线程未能成功中断线程b

3.1 InterruptedException异常介绍

线程内调用waitjoinsleep时都会进入阻塞状态。当线程处于阻塞状态时被中断,这时线程就会抛出InterruptedException异常,其实大家可以通俗的理解为一种通知即可。以sleep方法为例,大家可以按如下模拟实现来理解(底层是native实现):

public static void sleep(long millis) throws InterruptedException 
{
    while (/* still waiting for millis to become zero */) 
    {
        if (Thread.interrupted())
        {
            throw new InterruptedException();
        }
        // Keep waiting
    }
}

有了InterruptedException异常通知,线程就可以在阻塞时立即知道被中断了,进而采取一定的措施响应中断。需要注意的一点是,由于抛出了InterruptedException异常,因此不会在设置中断标志位。

3.2 考虑线程阻塞时如何优雅的停止一个线程

理解了InterruptedException异常,我们就可以在线程即使发生阻塞时也能成功进行中断了,如下所示:

public class TestMain {
    public static void main(String[] args) throws InterruptedException {
        Thread b = new Thread(new Runnable() {
            @Override
            public void run() {
                int num = 0;
                while(true) {
                    if (Thread.interrupted()) {
                        break;
                    }
                    try {
                        Thread.sleep(1000); // 用sleep来模拟线程的执行
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt(); // 注意这里是重点!
                    }
                    System.out.println("thread b running, num is:" + num++);
                }
            }
        });
        b.start();
        // 主线程sleep5.5秒,让线程b先循环5次
        Thread.sleep(5500);
        // 中断线程b
        b.interrupt();
    }
}

这里我们在检查到InterruptedException异常时,重新设置了中断标志位,这样下次循环一开始时,即可判断被中断了,进而退出循环体。当然我们可以在InterruptedException异常catch时直接退出。

4 总结

我们介绍了Java中的线程中断相关知识点,通俗来讲,大家可以理解为中断就是一种线程间相互打断的一种方式,比如两个线程aba如果在某一时刻想打断b的执行,则可以调用b.interrupt()方法进行中断,但是要注意,这里仅仅是设置b的中断状态位,b看到中断状态位后可以自行决定是否响应,当然,正常情况我们写的代码都需要做好中断状态位的判断(这一点大家在写业务代码时确实经常忽略)。另外对于阻塞中的线程,Java通过InterruptedException异常来进行通知。

推荐学习:《java视频教程

Atas ialah kandungan terperinci Pengenalan terperinci kepada gangguan benang di Jawa. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:juejin.im. Jika ada pelanggaran, sila hubungi admin@php.cn Padam