Mekanisme interupsi Thread adalah cara yang disukai untuk mendapatkan thread (yang bekerja sama) untuk merespons permintaan untuk menghentikan apa yang dilakukannya. Setiap utas (termasuk utas itu sendiri menurut saya) dapat memanggil utas interrupt()
.
Dalam praktiknya, kasus penggunaan normal untuk interrupt()
melibatkan beberapa jenis kerangka kerja atau manajer yang memberi tahu beberapa utas pekerja untuk menghentikan apa yang mereka lakukan. Jika thread pekerja adalah "interrupt aware", ia akan melihat bahwa ia telah diinterupsi melalui sebuah pengecualian, atau dengan secara berkala memeriksa flag interupsinya. Saat memperhatikan bahwa utas telah terputus, utas yang berperilaku baik akan meninggalkan apa yang dilakukannya dan berakhir dengan sendirinya.
Dengan asumsi kasus penggunaan di atas, kode Anda kemungkinan besar akan terganggu jika dijalankan dalam framework Java atau dari beberapa thread pekerja. Dan ketika terputus, kode Anda harus meninggalkan apa yang dilakukannya dan menyebabkan dirinya sendiri diakhiri dengan cara yang paling tepat. Bergantung pada bagaimana kode Anda dipanggil, ini mungkin dilakukan dengan mengembalikan atau dengan memberikan beberapa pengecualian yang sesuai. Tapi mungkin seharusnya tidak menelepon System.exit()
. (Aplikasi Anda tidak selalu tahu mengapa itu diinterupsi, dan pasti tidak tahu apakah ada utas lain yang perlu diinterupsi oleh kerangka kerja.)
Di sisi lain, jika kode Anda tidak dirancang untuk berjalan di bawah kendali beberapa kerangka kerja, Anda dapat membantah bahwa InterruptedException
ini adalah pengecualian yang tidak terduga; yaitu bug. Dalam hal ini, Anda harus memperlakukan pengecualian seperti halnya bug lainnya; misalnya membungkusnya dalam pengecualian yang tidak dicentang, dan menangkap serta mencatatnya pada titik yang sama saat Anda menangani pengecualian tidak dicentang yang tidak terduga lainnya. (Alternatifnya, aplikasi Anda dapat mengabaikan interupsi dan terus melakukan apa yang dilakukannya.)
1) Jika saya sendiri tidak pernah menyela utas lain, apa yang dapat memicu InterruptedException?
Salah satu contohnya adalah jika Runnable
objek Anda dieksekusi menggunakan ExecutorService
dan shutdownNow()
dipanggil pada layanan. Dan dalam teori, kumpulan utas pihak ketiga atau kerangka kerja manajemen utas dapat melakukan hal seperti ini secara sah.
2) Jika saya sendiri tidak pernah menyela utas lain menggunakan interrupt () ... lalu apa InterruptedException
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 >> bagian << aplikasi yang perlu Anda lakukan.
Sampai Anda tahu mengapa InterruptedException
dibuang, saya sarankan untuk memperlakukannya sebagai kesalahan yang sulit; misalnya mencetak stacktrace ke file log dan menutup aplikasi. (Jelas, itu tidak selalu merupakan jawaban yang benar ... tetapi intinya adalah bahwa ini adalah "bug", dan perlu diperhatikan oleh pengembang / pengelola.)
3) Bagaimana cara mengetahui siapa / apa yang menelepon interrupt()
?
Tidak ada jawaban yang bagus untuk ini. Yang terbaik yang bisa saya sarankan adalah mengatur breakpoint pada Thread.interrupt()
dan melihat tumpukan panggilan.
Seperti yang ditunjukkan orang lain, menyela utas (sebenarnya, menyela panggilan pemblokiran) biasanya digunakan untuk tujuan keluar dengan bersih atau membatalkan aktivitas yang sedang berlangsung.
Namun, Anda tidak boleh memperlakukan
InterruptedException
sendirian sebagai "perintah keluar". Alih-alih, Anda harus memikirkan interupsi sebagai alat untuk mengontrol status thread yang sedang berjalan, sama seperti yangObject.notify()
dilakukan. Dengan cara yang sama seperti Anda memeriksa keadaan saat ini setelah bangun dari panggilan keObject.wait()
(Anda tidak berasumsi bahwa bangun berarti kondisi tunggu Anda telah terpenuhi), setelah didorong dengan interupsi, Anda harus memeriksa mengapa Anda diinterupsi . Biasanya ada cara untuk melakukan ini. Misalnyajava.util.concurrent.FutureTask
memilikiisCancelled()
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(); }
sumber
Masalah dengan pertanyaan itu adalah "aku". "Saya" biasanya mengacu pada satu contoh kelas. Maksud saya dengan itu, bahwa bagian tertentu dari kode tingkat rendah (kelas) tidak boleh bergantung pada implementasi seluruh sistem. Karena itu Anda memang harus membuat beberapa keputusan "arsitektural" (seperti platform apa yang akan dijalankan).
Interupsi tak terduga yang mungkin datang dari JRE adalah tugas yang dibatalkan di
java.util.concurrent
dan mematikan applet.Penanganan interupsi thread biasanya ditulis dengan tidak benar. Oleh karena itu, saya menyarankan keputusan arsitektural untuk menghindari menyebabkan interupsi jika memungkinkan. Namun, interupsi penanganan kode harus selalu ditulis dengan benar. Tidak dapat mengambil interupsi dari platform sekarang.
sumber
Anda bisa mempelajarinya dengan membuat kelas thread Anda sendiri (extending
java.lang.Thread
) daninterrupt()
metode overriding , di mana Anda merekam stacktrace ke, katakanlah, kolom 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(); } }
sumber
Seperti yang telah disebutkan, pustaka lain dapat mengganggu utas Anda. Meskipun pustaka tidak memiliki akses eksplisit ke utas dari kode Anda, mereka masih bisa mendapatkan daftar utas yang sedang berjalan dan menghentikannya dengan cara itu dengan metode berikut .
sumber
Saya rasa saya mengerti mengapa Anda agak bingung tentang interupsi. Mohon pertimbangkan jawaban saya sejalan:
Pertama, Anda dapat mengganggu utas lainnya; Saya tahu bahwa di JCiP disebutkan bahwa Anda tidak boleh menginterupsi thread yang bukan milik Anda; Namun, pernyataan ini harus dipahami dengan benar. Artinya adalah bahwa kode Anda yang mungkin berjalan di utas arbitrer apa pun seharusnya tidak menangani gangguan karena karena ini bukan pemilik utas, kode tersebut tidak memiliki petunjuk tentang kebijakan interupsi. Jadi, Anda dapat meminta interupsi pada utas lain, tetapi biarkan pemiliknya mengambil tindakan interupsi; itu memiliki kebijakan interupsi yang dikemas di dalamnya, bukan kode tugas Anda; setidaknya bersikaplah sopan untuk memasang bendera interupsi!
Ada banyak cara mengapa masih ada interupsi, mungkin timeout, interupsi JVM, dll.
Anda harus sangat berhati-hati di sini; jika Anda memiliki utas yang melemparkan InterruptedException (IE), maka Anda tahu apa yang harus dilakukan setelah menangkapnya, katakanlah Anda dapat mematikan aplikasi / layanan Anda atau Anda dapat mengganti utas yang dimatikan ini dengan yang baru! Namun, jika Anda tidak memiliki utas, maka setelah menangkap IE, lontarkan ulang lebih tinggi ke tumpukan panggilan atau setelah melakukan sesuatu (mungkin logging), atur ulang status terputus sehingga kode yang memiliki utas ini, saat kontrol mencapainya, dapat belajar bahwa utas terputus dan karenanya mengambil tindakan sebagaimana mestinya karena hanya ia yang mengetahui kebijakan interupsi.
Semoga ini bisa membantu.
sumber
Kata-
InterruptedException
kata bahwa rutinitas mungkin terputus, tetapi tidak harus begitu.Jika Anda tidak mengharapkan interupsi, maka Anda harus memperlakukannya sebagai pengecualian tak terduga lainnya. Jika berada di bagian kritis di mana pengecualian tak terduga dapat memiliki konsekuensi yang mengerikan, mungkin yang terbaik adalah mencoba dan membersihkan sumber daya dan mematikan dengan baik (karena mendapatkan sinyal interupsi bahwa aplikasi Anda yang direkayasa dengan baik yang tidak bergantung pada interupsi sedang digunakan dengan cara yang tidak dirancang, jadi pasti ada sesuatu yang salah). Atau, jika kode yang dipermasalahkan adalah sesuatu yang tidak kritis atau sepele, Anda mungkin ingin mengabaikan (atau mencatat) interupsi dan melanjutkan.
sumber