Bạn có thể giải thích những gì java.lang.Thread.interrupt()
làm khi được gọi?
Bạn có thể giải thích những gì java.lang.Thread.interrupt()
làm khi được gọi?
Câu trả lời:
Thread.interrupt()
đặt trạng thái / cờ bị gián đoạn của luồng đích. Sau đó, mã đang chạy trong luồng đích đó CÓ THỂ thăm dò trạng thái bị gián đoạn và xử lý nó một cách thích hợp. Một số phương pháp chặn như Object.wait()
có thể tiêu thụ trạng thái bị gián đoạn ngay lập tức và đưa ra một ngoại lệ thích hợp (thông thường InterruptedException
)
Sự gián đoạn trong Java không phải là tiền đề. Đặt một cách khác cả hai luồng phải hợp tác để xử lý ngắt đúng cách. Nếu luồng đích không thăm dò trạng thái bị gián đoạn thì ngắt bị bỏ qua một cách hiệu quả.
Việc bỏ phiếu xảy ra thông qua Thread.interrupted()
phương thức trả về trạng thái bị gián đoạn của luồng hiện tại VÀ xóa cờ ngắt đó. Thông thường, luồng có thể làm một cái gì đó như ném Interrupttedception.
EDIT (từ nhận xét của Thilo): Một số phương thức API đã được tích hợp trong xử lý ngắt. Trên đỉnh đầu của tôi, điều này bao gồm.
Object.wait()
, Thread.sleep()
VàThread.join()
java.util.concurrent
cấu trúcInterruptedException
, thay vào đó sử dụng ClosedByInterruptException
.EDIT (từ câu trả lời của @ thomas-pornin cho chính xác câu hỏi tương tự )
Sự gián đoạn chủ đề là một cách nhẹ nhàng để nâng niu một chủ đề. Nó được sử dụng để cung cấp cho các chủ đề một cơ hội để thoát ra một cách sạch sẽ , trái ngược với Thread.stop()
điều đó giống như bắn các chủ đề bằng một khẩu súng trường tấn công.
Ngắt là gì?
Một ngắt là một dấu hiệu cho một luồng rằng nó sẽ dừng những gì nó đang làm và làm một cái gì đó khác. Lập trình viên quyết định chính xác cách một luồng phản ứng với một ngắt, nhưng điều này rất phổ biến đối với luồng kết thúc.
Nó được thực hiện như thế nào?
Cơ chế ngắt được thực hiện bằng cách sử dụng cờ nội bộ được gọi là trạng thái ngắt. Gọi Thread.interrupt đặt cờ này. Khi một luồng kiểm tra một ngắt bằng cách gọi phương thức tĩnh Thread.interrupted, trạng thái ngắt sẽ bị xóa. Thread.isInterrupted không tĩnh, được sử dụng bởi một luồng để truy vấn trạng thái ngắt của một luồng khác, không thay đổi cờ trạng thái ngắt.
Trích dẫn từ Thread.interrupt()
API :
Làm gián đoạn chủ đề này. Đầu tiên, phương thức checkAccess của luồng này được gọi, điều này có thể khiến SecurityException bị ném.
Nếu luồng này bị chặn trong một lời gọi của các phương thức Wait (), Wait (long) hoặc Wait (long, int) của lớp Object hoặc của hàm jo (), nối (dài), nối (long, int) , ngủ (dài) hoặc ngủ (dài, int), các phương thức của lớp này, sau đó trạng thái ngắt của nó sẽ bị xóa và nó sẽ nhận được InterruptedException.
Nếu luồng này bị chặn trong hoạt động I / O trên một kênh bị gián đoạn thì kênh đó sẽ bị đóng, trạng thái ngắt của luồng sẽ được đặt và luồng sẽ nhận được một ĐóngByInterruptException.
Nếu luồng này bị chặn trong Bộ chọn thì trạng thái ngắt của luồng sẽ được đặt và nó sẽ trả về ngay từ thao tác chọn, có thể với giá trị khác không, giống như khi phương thức đánh thức của bộ chọn được gọi.
Nếu không có điều kiện nào trước đó giữ thì trạng thái ngắt của luồng này sẽ được đặt.
Kiểm tra này để hiểu đầy đủ về cùng:
http://doad.oracle.com/javase/tutorial/essential/concurrency/interrupt.html
Nếu luồng được nhắm mục tiêu đã chờ đợi (bằng cách gọi wait()
hoặc một số phương thức liên quan khác về cơ bản làm điều tương tự, chẳng hạn như sleep()
), thì nó sẽ bị gián đoạn, có nghĩa là nó dừng chờ đợi những gì nó đang chờ và thay vào đó là InterruptedException.
Nó hoàn toàn phụ thuộc vào chính luồng (mã được gọi wait()
) để quyết định phải làm gì trong tình huống này. Nó không tự động chấm dứt chuỗi.
Nó đôi khi được sử dụng kết hợp với một cờ chấm dứt. Khi bị gián đoạn, luồng có thể kiểm tra cờ này và sau đó tự tắt. Nhưng một lần nữa, đây chỉ là một quy ước.
Để đầy đủ, ngoài các câu trả lời khác, nếu luồng bị gián đoạn trước khi chặn Object.wait(..)
hoặc Thread.sleep(..)
v.v., điều này tương đương với việc nó bị gián đoạn ngay lập tức khi chặn trên phương thức đó , như ví dụ sau đây cho thấy.
public class InterruptTest {
public static void main(String[] args) {
Thread.currentThread().interrupt();
printInterrupted(1);
Object o = new Object();
try {
synchronized (o) {
printInterrupted(2);
System.out.printf("A Time %d\n", System.currentTimeMillis());
o.wait(100);
System.out.printf("B Time %d\n", System.currentTimeMillis());
}
} catch (InterruptedException ie) {
System.out.printf("WAS interrupted\n");
}
System.out.printf("C Time %d\n", System.currentTimeMillis());
printInterrupted(3);
Thread.currentThread().interrupt();
printInterrupted(4);
try {
System.out.printf("D Time %d\n", System.currentTimeMillis());
Thread.sleep(100);
System.out.printf("E Time %d\n", System.currentTimeMillis());
} catch (InterruptedException ie) {
System.out.printf("WAS interrupted\n");
}
System.out.printf("F Time %d\n", System.currentTimeMillis());
printInterrupted(5);
try {
System.out.printf("G Time %d\n", System.currentTimeMillis());
Thread.sleep(100);
System.out.printf("H Time %d\n", System.currentTimeMillis());
} catch (InterruptedException ie) {
System.out.printf("WAS interrupted\n");
}
System.out.printf("I Time %d\n", System.currentTimeMillis());
}
static void printInterrupted(int n) {
System.out.printf("(%d) Am I interrupted? %s\n", n,
Thread.currentThread().isInterrupted() ? "Yes" : "No");
}
}
Đầu ra:
$ javac InterruptTest.java
$ java -classpath "." InterruptTest
(1) Am I interrupted? Yes
(2) Am I interrupted? Yes
A Time 1399207408543
WAS interrupted
C Time 1399207408543
(3) Am I interrupted? No
(4) Am I interrupted? Yes
D Time 1399207408544
WAS interrupted
F Time 1399207408544
(5) Am I interrupted? No
G Time 1399207408545
H Time 1399207408668
I Time 1399207408669
Hàm ý: nếu bạn lặp như sau và ngắt xảy ra tại thời điểm chính xác khi điều khiển rời đi Thread.sleep(..)
và đang đi vòng vòng, ngoại lệ vẫn sẽ xảy ra. Vì vậy, hoàn toàn an toàn khi dựa vào InterruptedException bị ném một cách đáng tin cậy sau khi chuỗi bị gián đoạn :
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException ie) {
break;
}
}
Thread.interrupt()
đặt trạng thái / cờ bị gián đoạn của luồng đích thành true mà khi được chọn sử dụng Thread.interrupted()
có thể giúp ngăn chặn luồng vô tận. Tham khảo http://www.yegor256.com/2015/10/20/interrupted-exception.html
Sự gián đoạn chủ đề được dựa trên trạng thái ngắt cờ . Đối với mỗi giá trị mặc định của trạng thái ngắt được đặt thành false . Bất cứ khi nào phương thức interrupt () được gọi trên luồng, trạng thái ngắt được đặt thành true .
ngắt khoảng trống công cộng ()
Làm gián đoạn chủ đề này.
Trừ khi luồng hiện tại tự ngắt, điều này luôn được cho phép, phương thức checkAccess của luồng này được gọi, điều này có thể khiến SecurityException bị ném.
Nếu luồng này bị chặn trong một lời gọi của các phương thức Wait (), Wait (long) hoặc Wait (long, int) của lớp Object hoặc của hàm jo (), nối (dài), nối (long, int) , ngủ (dài) hoặc ngủ (dài, int), các phương thức của lớp này, sau đó trạng thái ngắt của nó sẽ bị xóa và nó sẽ nhận được InterruptedException.
Nếu luồng này bị chặn trong hoạt động I / O trên một kênh bị gián đoạn thì kênh đó sẽ bị đóng, trạng thái ngắt của luồng sẽ được đặt và luồng sẽ nhận được một ĐóngByInterruptException.
Nếu luồng này bị chặn trong Bộ chọn thì trạng thái ngắt của luồng sẽ được đặt và nó sẽ trả về ngay từ thao tác chọn, có thể với giá trị khác không, giống như khi phương thức đánh thức của bộ chọn được gọi.
Nếu không có điều kiện nào trước đó giữ thì trạng thái ngắt của luồng này sẽ được đặt.
Làm gián đoạn một chủ đề không còn sống không cần có bất kỳ ảnh hưởng nào.
Ném: SecurityException - nếu luồng hiện tại không thể sửa đổi luồng này
Một ngắt là một dấu hiệu cho một luồng rằng nó sẽ dừng những gì nó đang làm và làm một cái gì đó khác. Lập trình viên quyết định chính xác cách một luồng phản ứng với một ngắt, nhưng điều này rất phổ biến đối với luồng kết thúc. Một giới thiệu rất tốt: https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html
Phương thức Thread.interrupt () thiết lập cờ 'trạng thái ngắt' bên trong. Thông thường cờ đó được kiểm tra bằng phương thức Thread.interrupted ().
Theo quy ước, bất kỳ phương thức nào tồn tại thông qua InterruptedException đều phải xóa cờ trạng thái ngắt.