Jawaban:
Ini dilakukan untuk menjaga status .
Ketika Anda menangkap InterruptException
dan menelannya, pada dasarnya Anda mencegah metode / grup utas tingkat tinggi dari memperhatikan interupsi. Yang bisa menyebabkan masalah.
Dengan menelepon Thread.currentThread().interrupt()
, Anda mengatur bendera interupsi utas, sehingga penangan interupsi tingkat yang lebih tinggi akan melihatnya dan dapat menanganinya dengan tepat.
Java Concurrency in Practice membahas ini secara lebih rinci di Bab 7.1.3: Menanggapi Gangguan . Aturannya adalah:
Hanya kode yang menerapkan kebijakan interupsi utas yang dapat menelan permintaan interupsi. Tugas dan kode pustaka untuk tujuan umum tidak boleh menelan permintaan interupsi.
interrupt()
panggilan adalah satu-satunya cara untuk mengatur bendera yang terputus begitu Anda menerima pemberitahuan tentang keadaan ini melalui "mekanisme pengiriman" lainnya - InterruptedException
dan ingin atau tidak dapat melemparkan kembali.
Saya pikir contoh kode ini membuat semuanya lebih jelas. Kelas yang melakukan pekerjaan:
public class InterruptedSleepingThread extends Thread {
@Override
public void run() {
doAPseudoHeavyWeightJob();
}
private void doAPseudoHeavyWeightJob() {
for (int i=0;i<Integer.MAX_VALUE;i++) {
//You are kidding me
System.out.println(i + " " + i*2);
//Let me sleep <evil grin>
if(Thread.currentThread().isInterrupted()) {
System.out.println("Thread interrupted\n Exiting...");
break;
}else {
sleepBabySleep();
}
}
}
/**
*
*/
protected void sleepBabySleep() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//e.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
Kelas Utama:
public class InterruptedSleepingThreadMain {
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
InterruptedSleepingThread thread = new InterruptedSleepingThread();
thread.start();
//Giving 10 seconds to finish the job.
Thread.sleep(10000);
//Let me interrupt
thread.interrupt();
}
}
Coba panggil interupsi tanpa mengembalikan status.
catatan:
Bagaimana cara menghentikan utas yang menunggu dalam waktu lama (mis., Untuk input)?
Agar teknik ini berfungsi, sangat penting bahwa setiap metode yang menangkap pengecualian interupsi dan tidak siap untuk menanganinya segera memasukkan kembali pengecualian. Kami mengatakan memasukkan kembali daripada memikirkan kembali, karena tidak selalu mungkin untuk memikirkan kembali pengecualian. Jika metode yang menangkap InterruptedException tidak dinyatakan untuk melempar pengecualian (dicentang) ini, maka metode itu harus "menyela kembali dirinya sendiri" dengan mantra berikut:
Thread.currentThread().interrupt();
Ini memastikan bahwa Thread akan membangkitkan kembali InterruptedException secepatnya.
Saya akan menganggapnya sebagai praktik yang buruk atau setidaknya sedikit berisiko. Biasanya metode tingkat yang lebih tinggi tidak melakukan operasi pemblokiran dan mereka tidak akan pernah melihat di InterruptedException
sana. Jika Anda menyembunyikannya di setiap tempat Anda melakukan operasi interupsi, Anda tidak akan pernah mendapatkannya.
Satu-satunya alasan untuk Thread.currentThread.interrupt()
dan tidak meningkatkan pengecualian lain atau menandakan permintaan interupsi dengan cara lain (misalnya mengatur interrupted
variabel variabel lokal di loop utama utas) adalah situasi di mana Anda benar-benar tidak dapat melakukan apa pun dengan pengecualian, seperti di finally
blok.
Lihat jawaban Péter Török, jika Anda ingin lebih memahami implikasi Thread.currentThread.interrupt()
panggilan tersebut.
Rujuk dari java doc
Jika utas ini diblokir dalam permohonan wait (), join (), sleep (long), maka status interruptnya akan dihapus dan ia akan menerima InterruptedException.
Jika utas ini diblokir dalam operasi I / O, 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.
Jika tidak ada kondisi sebelumnya yang bertahan maka status interupsi utas ini akan ditetapkan.
Jadi, jika Anda mengubah metode sleepBabySleep () di @Ajay George Answer untuk operasi I / O atau hanya sysout, Anda tidak perlu mengatur status kembali untuk menghentikan program. (BTW, mereka bahkan tidak membuang InterruptedException)
Sama seperti @ Péter Török berkata => Ini dilakukan untuk menjaga status. (Dan khusus untuk metode yang akan membuang InterruptedException)
InterruptedException
status interupsi yang jelas ketika melakukannya. Saya pikir ini membuat jawaban lebih jelas dalam hal mengapa Anda perlu mempertahankan status interupsi.