Saya berharap bahwa JVM dengan anggun menyela ( thread.interrupt()
) semua utas yang berjalan yang dibuat oleh aplikasi, setidaknya untuk sinyal SIGINT (kill -2)
dan SIGTERM (kill -15)
.
Dengan cara ini, sinyal akan diteruskan kepada mereka, memungkinkan pembatalan thread dengan anggun dan penyelesaian sumber daya dengan cara standar .
Tapi ini tidak terjadi (setidaknya dalam implementasi JVM saya: Java(TM) SE Runtime Environment (build 1.8.0_25-b17), Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)
.
Seperti yang dikomentari pengguna lain, penggunaan hook shutdown tampaknya wajib.
Jadi, bagaimana cara mengatasinya?
Pertama-tama, saya tidak peduli tentang itu di semua program, hanya di program di mana saya ingin melacak pembatalan pengguna dan tujuan yang tidak terduga. Misalnya, bayangkan program java Anda adalah proses yang dikelola oleh orang lain. Anda mungkin ingin membedakan apakah telah dihentikan dengan baik ( SIGTERM
dari proses manajer) atau telah terjadi pemadaman (untuk meluncurkan kembali pekerjaan secara otomatis saat permulaan).
Sebagai dasar, saya selalu membuat utas saya yang sudah berjalan lama secara berkala menyadari status terputus dan melempar InterruptedException
jika mereka terputus. Ini memungkinkan penyelesaian eksekusi dengan cara yang dikontrol oleh pengembang (juga menghasilkan hasil yang sama seperti operasi pemblokiran standar). Kemudian, di tingkat atas tumpukan benang, InterruptedException
ditangkap dan pembersihan yang sesuai dilakukan. Utas ini diberi kode untuk mengetahui cara menanggapi permintaan interupsi. Desain kohesi tinggi .
Jadi, dalam kasus ini, saya menambahkan hook shutdown, yang menurut saya harus dilakukan JVM secara default: interupsi semua utas non-daemon yang dibuat oleh aplikasi saya yang masih berjalan:
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.out.println("Interrupting threads");
Set<Thread> runningThreads = Thread.getAllStackTraces().keySet();
for (Thread th : runningThreads) {
if (th != Thread.currentThread()
&& !th.isDaemon()
&& th.getClass().getName().startsWith("org.brutusin")) {
System.out.println("Interrupting '" + th.getClass() + "' termination");
th.interrupt();
}
}
for (Thread th : runningThreads) {
try {
if (th != Thread.currentThread()
&& !th.isDaemon()
&& th.isInterrupted()) {
System.out.println("Waiting '" + th.getName() + "' termination");
th.join();
}
} catch (InterruptedException ex) {
System.out.println("Shutdown interrupted");
}
}
System.out.println("Shutdown finished");
}
});
Lengkapi aplikasi pengujian di github: https://github.com/idelvall/kill-test
kill -9
bagi saya berarti: "Pergilah, proses busuk, pergi bersamamu!", di mana proses itu akan berhenti. Segera.