Apa yang dilakukan java.lang.Thread.interrupt ()?

Jawaban:

251

Thread.interrupt()mengatur status / bendera terputus dari utas target. Kemudian kode yang berjalan di utas target itu MUNGKIN mengumpulkan status terputus dan menanganinya dengan tepat. Beberapa metode yang memblokir seperti Object.wait()dapat langsung mengkonsumsi status terputus dan melemparkan pengecualian yang sesuai (biasanya InterruptedException)

Gangguan di Jawa tidak bersifat pre-emptive. Dengan kata lain kedua utas harus bekerja sama untuk memproses interupsi dengan benar. Jika utas target tidak menyurvei status terputus, interupsi secara efektif diabaikan.

Polling terjadi melalui Thread.interrupted()metode yang mengembalikan status terputus utas saat ini DAN menghapus tanda tersebut. Biasanya utas kemudian dapat melakukan sesuatu seperti melempar InterruptedException.

EDIT (dari komentar Thilo): Beberapa metode API telah dibangun dalam penanganan interupsi. Dari atas kepala saya ini termasuk.

  • Object.wait(),, Thread.sleep()danThread.join()
  • Sebagian besar java.util.concurrentstruktur
  • Java NIO (tetapi bukan java.io) dan TIDAK digunakan InterruptedException, alih-alih menggunakan ClosedByInterruptException.

EDIT (dari jawaban @ thomas-pornin untuk pertanyaan yang sama persis untuk kelengkapan)

Interupsi utas adalah cara yang lembut untuk mendorong utas. Ini digunakan untuk memberi kesempatan pada thread untuk keluar dengan bersih , sebagai lawan dari Thread.stop()itu lebih seperti menembak utas dengan senapan serbu.

Mike Q
sumber
22
Perhatikan bahwa metode seperti tidur atau menunggu melakukan jajak pendapat semacam ini dan melemparkan sendiri InterruptedException.
Thilo
1
Jika Anda menggunakan file I / O yang dapat terputus, efeknya tidak akan terlalu lembut. Anda biasanya akan mendapatkan file korupsi.
Marko Topolnik
jika Anda menyebutkan Thread.interrupted, sepertinya harus disebutkan bahwa ada juga Thread.isInterrupted flag, yang tidak menghapus flag, yang membuatnya biasanya lebih tepat untuk digunakan oleh pengembang aplikasi.
Nathan Hughes
67

Apa itu interupsi?

Interupsi adalah indikasi untuk utas bahwa ia harus menghentikan apa yang dilakukannya dan melakukan sesuatu yang lain. Terserah programmer untuk memutuskan dengan tepat bagaimana sebuah thread merespon interupsi, tetapi sangat umum bagi thread untuk mengakhiri.

Bagaimana penerapannya?

Mekanisme interupsi diimplementasikan menggunakan bendera internal yang dikenal sebagai status interupsi. Invoking Thread.interrupt mengatur flag ini. Ketika utas memeriksa interupsi dengan menjalankan metode statis Thread.interrupted, status interupsi dihapus. Thread.isInterrupted non-statis, yang digunakan oleh satu utas untuk menanyakan status interupsi yang lain, tidak mengubah bendera status interupsi.

Kutipan dari Thread.interrupt()API :

Mengganggu utas ini. Pertama metode checkAccess dari utas ini dipanggil, yang dapat menyebabkan SecurityException dilempar.

Jika utas ini diblokir dalam permohonan metode wait (), wait (long), atau wait (long, int) dari kelas Object, atau dari join (), join (long), join (long, int) , sleep (long), atau sleep (long, int), metode kelas ini, maka status interruptnya akan dihapus dan ia akan menerima InterruptedException.

Jika utas ini diblokir dalam operasi I / O pada saluran interruptible maka saluran akan ditutup, status interupsi utas akan ditetapkan, dan utas akan menerima ClosedByInterruptException.

Jika utas ini diblokir dalam Pemilih maka status interupsi utas akan ditetapkan dan akan segera kembali dari operasi pemilihan, mungkin dengan nilai bukan nol, sama seperti jika metode bangun pemilih dipanggil.

Jika tidak ada kondisi sebelumnya yang bertahan maka status interupsi utas ini akan ditetapkan.

Lihat ini untuk pemahaman lengkap tentang hal yang sama:

http://download.oracle.com/javase/tutorial/essential/concurrency/interrupt.html

YoK
sumber
Ini mematuhi sebagian penjelasan. Ini juga menginterupsi metode interruptible.
Marquis of Lorne
@ EJP Pertanyaan ini tentang, apa itu metode Thread.interrupt () dan bagaimana cara kerjanya. Saya pikir apa pun yang saya posting dengan tautan, menjawab apa yang ditanyakan. Saya masih tidak mengerti apa yang Anda inginkan?
YoK
Saya berharap Anda memperbaiki pernyataan yang salah sebagian bahwa itu diterapkan oleh sebuah bendera. Itu hanya sebagian dari cerita. Tampaknya cukup jelas bagi saya.
Marquis of Lorne
@ EJP Terima kasih. Sekarang saya mengerti apa yang Anda katakan. Saya telah memperbarui jawaban saya dan menambahkan API doc untuk metode. Ini mencakup bagian metode interruptible yang hilang dari jawaban saya. Semoga jawaban saya terlihat lengkap sekarang :).
YoK
13

Jika utas yang ditargetkan telah menunggu (dengan menelepon wait(), atau beberapa metode terkait lainnya yang pada dasarnya melakukan hal yang sama, seperti sleep()), itu akan terputus, artinya berhenti menunggu apa yang ditunggu dan menerima InterruptedException sebagai gantinya.

Ini sepenuhnya tergantung pada utas itu sendiri (kode yang memanggil wait()) untuk memutuskan apa yang harus dilakukan dalam situasi ini. Itu tidak secara otomatis menghentikan utas.

Kadang-kadang digunakan dalam kombinasi dengan bendera penghentian. Ketika terputus, utas dapat memeriksa bendera ini, lalu menutupnya sendiri. Tetapi sekali lagi, ini hanya sebuah konvensi.

Thilo
sumber
9 tahun, jawaban awet muda! +1
snr
10

Untuk kelengkapan, di samping jawaban lain, jika utas terputus sebelum ia memblokir Object.wait(..)atau Thread.sleep(..)lain - lain, ini setara dengan itu terputus segera setelah memblokir pada metode itu , seperti yang ditunjukkan contoh berikut.

public class InterruptTest {
    public static void main(String[] args) {

        Thread.currentThread().interrupt();

        printInterrupted(1);

        Object o = new Object();
        try {
            synchronized (o) {
                printInterrupted(2);
                System.out.printf("A Time %d\n", System.currentTimeMillis());
                o.wait(100);
                System.out.printf("B Time %d\n", System.currentTimeMillis());
            }
        } catch (InterruptedException ie) {
            System.out.printf("WAS interrupted\n");
        }
        System.out.printf("C Time %d\n", System.currentTimeMillis());

        printInterrupted(3);

        Thread.currentThread().interrupt();

        printInterrupted(4);

        try {
            System.out.printf("D Time %d\n", System.currentTimeMillis());
            Thread.sleep(100);
            System.out.printf("E Time %d\n", System.currentTimeMillis());
        } catch (InterruptedException ie) {
            System.out.printf("WAS interrupted\n");
        }
        System.out.printf("F Time %d\n", System.currentTimeMillis());

        printInterrupted(5);

        try {
            System.out.printf("G Time %d\n", System.currentTimeMillis());
            Thread.sleep(100);
            System.out.printf("H Time %d\n", System.currentTimeMillis());
        } catch (InterruptedException ie) {
            System.out.printf("WAS interrupted\n");
        }
        System.out.printf("I Time %d\n", System.currentTimeMillis());

    }
    static void printInterrupted(int n) {
        System.out.printf("(%d) Am I interrupted? %s\n", n,
                Thread.currentThread().isInterrupted() ? "Yes" : "No");
    }
}

Keluaran:

$ javac InterruptTest.java 

$ java -classpath "." InterruptTest
(1) Am I interrupted? Yes
(2) Am I interrupted? Yes
A Time 1399207408543
WAS interrupted
C Time 1399207408543
(3) Am I interrupted? No
(4) Am I interrupted? Yes
D Time 1399207408544
WAS interrupted
F Time 1399207408544
(5) Am I interrupted? No
G Time 1399207408545
H Time 1399207408668
I Time 1399207408669

Implikasi: jika Anda mengulangi seperti berikut, dan interupsi terjadi pada saat yang tepat ketika kontrol telah pergi Thread.sleep(..)dan berkeliling loop, pengecualian masih akan terjadi. Jadi, sangat aman untuk mengandalkan InterruptedException yang andal dilemparkan setelah utas terputus :

while (true) {
    try {
        Thread.sleep(10);
    } catch (InterruptedException ie) {
        break;
    }
}
Evgeni Sergeev
sumber
4

Interupsi utas didasarkan pada status interupsi bendera . Untuk setiap utas nilai default dari status interupsi disetel ke false . Kapanpun metode interupsi () dipanggil pada utas, status interupsi disetel ke true .

  1. Jika interrupt status = true (interrupt () sudah dipanggil di utas), utas tertentu itu tidak bisa tidur. Jika tidur disebut bahwa utas terputus pengecualian dilemparkan. Setelah melempar pengecualian lagi, flag disetel ke false.
  2. Jika utas sudah tidur dan interupsi () dipanggil, utas akan keluar dari status tidur dan membuang Pengecualian yang terputus.
akash G
sumber
1

public void interrupt ()

Mengganggu utas ini.

Kecuali jika utas saat ini mengganggu dirinya sendiri, yang selalu diizinkan, metode checkAccess dari utas ini dipanggil, yang dapat menyebabkan SecurityException dilempar.

Jika utas ini diblokir dalam permohonan metode wait (), wait (long), atau wait (long, int) dari kelas Object, atau dari join (), join (long), join (long, int) , sleep (long), atau sleep (long, int), metode kelas ini, maka status interruptnya akan dihapus dan ia akan menerima InterruptedException.

Jika utas ini diblokir dalam operasi I / O pada saluran interruptible maka saluran akan ditutup, status interupsi utas akan ditetapkan, dan utas akan menerima ClosedByInterruptException.

Jika utas ini diblokir dalam Pemilih maka status interupsi utas akan ditetapkan dan akan segera kembali dari operasi pemilihan, mungkin dengan nilai bukan nol, sama seperti jika metode bangun pemilih dipanggil.

Jika tidak ada kondisi sebelumnya yang bertahan maka status interupsi utas ini akan ditetapkan.

Mengganggu utas yang tidak hidup tidak perlu memiliki efek apa pun.

Melempar: SecurityException - jika utas saat ini tidak dapat mengubah utas ini

Ajeet Ganga
sumber
1

Interupsi adalah indikasi untuk utas bahwa ia harus menghentikan apa yang dilakukannya dan melakukan sesuatu yang lain. Terserah programmer untuk memutuskan dengan tepat bagaimana sebuah thread merespon interupsi, tetapi sangat umum bagi thread untuk mengakhiri. Referensi yang sangat bagus: https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html

Adi
sumber
1

Metode Thread.interrupt () menetapkan flag 'interrupt status' internal. Biasanya flag itu dicentang dengan metode Thread.interrupted ().

Dengan konvensi, metode apa pun yang ada melalui InterruptedException harus menghapus tanda status interupsi.

Shuba Anatoliy
sumber