Tôi mong đợi rằng JVM ngắt ( thread.interrupt()
) tất cả các luồng đang chạy được tạo bởi ứng dụng, ít nhất là đối với các tín hiệu SIGINT (kill -2)
và SIGTERM (kill -15)
.
Bằng cách này, tín hiệu sẽ được chuyển tiếp đến chúng, cho phép hủy luồng một cách duyên dáng và hoàn thiện tài nguyên theo những cách tiêu chuẩn .
Nhưng đây không phải là trường hợp (ít nhất là trong việc thực hiện JVM của tôi: Java(TM) SE Runtime Environment (build 1.8.0_25-b17), Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)
.
Như những người dùng khác nhận xét, việc sử dụng móc tắt máy dường như là bắt buộc.
Vì vậy, tôi sẽ xử lý nó như thế nào?
Đầu tiên, tôi không quan tâm đến nó trong tất cả các chương trình, chỉ ở những chương trình mà tôi muốn theo dõi các lần hủy của người dùng và kết thúc không mong muốn. Ví dụ: hãy tưởng tượng rằng chương trình java của bạn là một quá trình được quản lý bởi khác. Bạn có thể muốn phân biệt xem nó đã được kết thúc một cách duyên dáng ( SIGTERM
từ quy trình của người quản lý) hay đã xảy ra tắt máy (để tự động khởi chạy lại công việc khi khởi động).
Về cơ bản, tôi luôn định kỳ để các luồng chạy dài của mình nhận biết được trạng thái bị gián đoạn và ném InterruptedException
nếu chúng bị gián đoạn. Điều này cho phép hoàn tất quá trình thực thi theo cách do nhà phát triển kiểm soát (cũng tạo ra kết quả tương tự như các hoạt động chặn tiêu chuẩn). Sau đó, ở cấp cao nhất của ngăn xếp luồng, InterruptedException
được ghi lại và thực hiện dọn dẹp thích hợp. Các luồng này được mã hóa để biết cách đáp ứng yêu cầu gián đoạn. Thiết kế có tính gắn kết cao .
Vì vậy, trong những trường hợp này, tôi thêm một móc tắt máy, đó là điều tôi nghĩ JVM nên làm theo mặc định: ngắt tất cả các luồng không phải daemon được tạo bởi ứng dụng của tôi vẫn đang chạy:
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");
}
});
Hoàn thành đơn đăng ký thử nghiệm tại github: https://github.com/idelvall/kill-test
kill -9
có nghĩa là với tôi: "Hãy bỏ qua, quá trình xấu xa, hãy bỏ đi với bạn!", theo đó quá trình sẽ chấm dứt. Ngay.