Pertanyaan Siapa yang memanggil metode Java Thread interrupt () jika saya tidak?


Saya telah membaca dan membaca kembali Java Concurrency in Practice, saya telah membaca beberapa utas di sini tentang masalah ini, saya telah membaca artikel IBM Berurusan dengan InterruptedException namun ada sesuatu yang tidak saya pahami yang menurut saya dapat dibagi menjadi dua pertanyaan:

  1. Jika saya tidak pernah mengganggu sendiri utas lainnya, apa yang bisa memicu InterruptedException?

  2. Jika saya tidak pernah mengganggu jalinan benang lain yang saya gunakan mengganggu() (katakan karena saya menggunakan cara lain untuk membatalkan utas kerja saya, seperti pil racun dan sementara (! dibatalkan) style loop [seperti yang dijelaskan di JCIP]), apa artinya an InterruptedException lalu artinya? Apa yang harus saya lakukan setelah menangkapnya? Matikan aplikasi saya?


76
2018-01-24 12:25


asal


Jawaban:


Mekanisme interupsi Thread adalah cara yang lebih disukai untuk mendapatkan thread (bekerja sama) untuk merespon permintaan untuk menghentikan apa yang sedang dilakukannya. Setiap thread (termasuk benang itu sendiri saya pikir) bisa menelepon interrupt() pada sebuah Thread.

Dalam prakteknya, kasus penggunaan normal untuk interrupt() melibatkan beberapa jenis kerangka kerja atau manajer yang memberitahukan beberapa pekerja untuk menghentikan apa yang mereka lakukan. Jika thread pekerja "interrupt aware", ia akan menyadari bahwa interupsi telah melalui pengecualian, atau dengan secara berkala memeriksa bendera yang terganggu. Menyadari bahwa itu telah terputus, benang yang berperilaku baik akan meninggalkan apa yang dilakukannya dan mengakhiri dirinya sendiri.

Dengan asumsi kasus penggunaan di atas, kode Anda kemungkinan akan terganggu jika dijalankan dalam kerangka Java atau dari beberapa utas pekerja. Dan ketika itu terganggu, kode Anda harus mengabaikan apa yang dilakukannya dan menyebabkan dirinya berakhir dengan sarana yang paling tepat. Tergantung pada bagaimana kode Anda dipanggil, ini mungkin dilakukan dengan mengembalikan atau dengan melemparkan beberapa pengecualian yang sesuai. Tapi mungkin seharusnya tidak menelepon System.exit(). (Aplikasi Anda tidak perlu tahu mengapa itu terganggu, dan tentu saja tidak tahu apakah ada benang lain yang perlu diganggu oleh kerangka kerja.)

Di sisi lain, jika kode Anda tidak dirancang untuk berjalan di bawah kendali beberapa kerangka kerja, Anda dapat membantah bahwa InterruptedException adalah pengecualian yang tidak terduga; yaitu bug. Dalam hal ini, Anda harus memperlakukan pengecualian seperti yang Anda lakukan terhadap bug lain; misalnya membungkusnya dalam pengecualian yang tidak terkendali, dan menangkap dan mencatatnya pada titik yang sama dengan yang Anda hadapi dengan pengecualian tak terduga lainnya yang tak terduga. (Atau, aplikasi Anda hanya bisa mengabaikan interupsi dan terus melakukan apa yang sedang dilakukan.)


1) Jika saya tidak pernah mengganggu sendiri utas lainnya, apa yang dapat memicu InterruptedException?

Salah satu contohnya adalah jika Anda Runnable objek dijalankan menggunakan ExecutorService dan shutdownNow() dipanggil di layanan. Dan secara teori, setiap kumpulan thread pihak ke-3 atau kerangka manajemen thread dapat secara sah melakukan sesuatu seperti ini.

2) Jika saya tidak pernah mengganggu benang lain sendiri dengan menggunakan interrupt () ... apa yang an InterruptedExceptionlalu artinya? Apa yang harus saya lakukan setelah menangkapnya? Matikan aplikasi saya?

Anda perlu menganalisis basis kode untuk mencari tahu apa yang membuat interrupt() panggilan dan mengapa. Setelah Anda mengetahuinya, Anda dapat menentukan apa yang harus Anda lakukan.

Sampai Anda tahu mengapa InterruptedException sedang dilempar, saya akan menyarankan memperlakukannya sebagai kesalahan keras; misalnya mencetak stacktrace ke file log dan mematikan aplikasi. (Jelas, itu tidak selalu jawaban yang benar ... tetapi intinya adalah ini adalah "bug", dan itu perlu dibawa ke perhatian pengembang / pemelihara.)

3) Bagaimana cara mengetahui siapa / apa yang ditelepon interrupt()?

Tidak ada jawaban yang bagus untuk ini. Yang terbaik yang bisa saya sarankan adalah mengatur breakpoint pada Thread.interrupt() dan lihat tumpukan panggilan.


44
2018-01-24 14:41



Jika Anda memutuskan untuk mengintegrasikan kode Anda dengan pustaka lain, mereka dapat menelepon interrupt() pada kode Anda. misalnya jika Anda memutuskan di masa depan untuk mengeksekusi kode Anda di dalam ExecutorService, maka itu dapat memaksa shutdown melalui interrupt().

Singkatnya, saya akan mempertimbangkan tidak hanya di mana kode Anda berjalan sekarang, tetapi dalam konteks apa itu dapat berjalan di masa depan. misalnya apakah kamu akan menaruhnya di perpustakaan? Wadah? Bagaimana orang lain akan menggunakannya? Apakah Anda akan menggunakannya kembali?


12
2018-01-24 12:43



Seperti yang telah ditunjukkan oleh orang lain, mengganggu utas (sebenarnya, mengganggu panggilan pemblokiran) biasanya digunakan untuk tujuan keluar bersih atau membatalkan kegiatan yang sedang berlangsung.

Namun, Anda seharusnya tidak memperlakukan InterruptedException sendirian sebagai "perintah berhenti". Sebagai gantinya, Anda harus memikirkan interupsi sebagai cara untuk mengontrol status running dari thread, banyak dengan cara yang sama Object.notify() tidak. Dengan cara yang sama Anda akan memeriksa keadaan saat ini setelah bangun dari panggilan ke Object.wait() (Anda tidak menganggap bahwa wakeup berarti kondisi menunggu Anda telah dipenuhi), setelah disisipkan dengan interupsi yang harus Anda periksa Mengapa Anda terganggu. Biasanya ada cara untuk melakukan ini. Sebagai contoh, java.util.concurrent.FutureTask memiliki isCancelled() metode.

Contoh kode:

public void run() {
    ....
    try {
        .... // Calls that may block.
    } catch (InterruptedException e) {
        if (!running) {  // Add preferred synchronization here.
            return; // Explicit flag says we should stop running.
        }
        // We were interrupted, but the flag says we're still running.
        // It would be wrong to always exit here. The interrupt 'nudge'
        // could mean something completely different. For example, it
        // could be that the thread was blocking on a read from a particular
        // file, and now we should read from a different file.
        // Interrupt != quit (not necessarily).
    }
    ....
}
public void stop() {
    running = false; // Add preferred synchronization here.
    myThread.interrupt();
}

9
2017-10-12 08:38



Masalahnya adalah "I". "Saya" biasanya mengacu pada satu kelas tunggal. Maksud saya dengan itu, bahwa setiap bagian khusus dari kode tingkat rendah (kelas) tidak boleh bergantung pada implementasi seluruh sistem. Setelah mengatakan bahwa Anda telah membuat beberapa keputusan "arsitektur" (seperti platform apa yang harus dijalankan).

Kemungkinan interupsi tak terduga yang datang dari JRE adalah tugas yang dibatalkan java.util.concurrent dan mematikan applet.

Penanganan interupsi benang biasanya salah ditulis. Oleh karena itu, saya menyarankan keputusan arsitektural untuk menghindari menyebabkan interupsi di mana mungkin. Namun, penanganan kode interupsi harus selalu ditulis dengan benar. Tidak dapat mengambil interupsi dari platform sekarang.


3
2018-01-24 16:39



Anda bisa mempelajari ini dengan membuat kelas thread Anda sendiri (memanjang java.lang.Thread) dan menimpa interrupt() metode, di mana Anda merekam stacktrace ke, katakanlah, bidang String, dan kemudian transfer ke super.interrupt ().

public class MyThread extends Thread {

    public volatile String interruptStacktrace; // Temporary field for debugging purpose.

    @Override
    public void interrupt() {
        interruptStacktrace = dumpStack(); // You implement it somehow...

        super.interrupt();
    }
}

2
2017-11-12 11:02



Seperti yang sudah disebutkan, pustaka lain dapat mengganggu untaian Anda. Bahkan jika pustaka tidak memiliki akses eksplisit ke untaian dari kode Anda, mereka masih bisa mendapatkan daftar untaian yang berjalan dan menyela mereka seperti itu dengan yang berikut ini metode.


1
2018-01-24 18:10



Itu InterruptedException mengatakan itu rutin mungkin terputus, tetapi tidak harus seperti itu.

Jika Anda tidak mengharapkan interupsi maka Anda harus memperlakukannya seperti Anda mungkin pengecualian tak terduga lainnya. Jika berada di bagian kritis di mana pengecualian yang tak terduga dapat menimbulkan konsekuensi yang keji, mungkin lebih baik untuk mencoba dan membersihkan sumber daya dan mematikan secara anggun (karena mendapatkan sinyal interupsi bahwa aplikasi Anda yang dirancang dengan baik yang tidak bergantung pada interupsi sedang digunakan dengan cara itu tidak dirancang, dan jadi pasti ada sesuatu yang salah). Alternatifnya, jika kode yang dimaksud adalah sesuatu yang tidak kritis atau sepele, Anda mungkin ingin mengabaikan (atau mencatat) interupsi dan terus berjalan.


0
2018-01-24 13:03