Java.lang.Thread.interrupt () làm gì?


Câu trả lời:


250

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()Thread.join()
  • Hầu hết các java.util.concurrentcấu trúc
  • Java NIO (nhưng không phải java.io) và nó KHÔNG sử dụng InterruptedException, 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.


22
Lưu ý rằng các phương pháp như ngủ hoặc chờ đợi thực hiện loại bỏ phiếu này và tự ném Interrupttedception.
Thilo

1
Nếu bạn đang sử dụng I / O tệp bị gián đoạn, hiệu ứng sẽ không được nhẹ nhàng. Thông thường bạn sẽ nhận được tham nhũng tập tin.
Marko Topolnik

nếu bạn đang đề cập đến Thread.interrupted, có vẻ như cũng nên đề cập rằng cũng có một cờ Thread.isInterrupted, không xóa cờ, điều này thường làm cho nó được sử dụng bởi các nhà phát triển ứng dụng.
Nathan Hughes

67

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


Đây là tuân theo một lời giải thích một phần. Nó cũng làm gián đoạn các phương pháp gián đoạn.
Hầu tước Lorne

@EJP Câu hỏi này là về, phương thức Thread.interrupt () là gì và nó hoạt động như thế nào. Tôi nghĩ bất cứ điều gì tôi đã đăng với liên kết, trả lời những gì được hỏi. Tôi vẫn không hiểu bạn mong muốn điều gì?
YoK

Tôi muốn bạn sửa lại tuyên bố không đúng một phần của bạn rằng nó được thực hiện bởi một cờ. Đó chỉ là một phần của câu chuyện. Nó có vẻ khá rõ ràng với tôi.
Hầu tước Lorne

@EJP Cảm ơn. Bây giờ tôi hiểu những gì bạn đang nói. Tôi đã cập nhật câu trả lời của mình và thêm tài liệu API cho phương thức. Điều này bao gồm một phần phương pháp gián đoạn mà thiếu câu trả lời của tôi. Hy vọng câu trả lời của tôi có vẻ hoàn chỉnh bây giờ :).
YoK

13

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.


9 tuổi, trả lời nhanh! +1
snr

10

Để đầ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;
    }
}


4

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 .

  1. Nếu trạng thái ngắt = true (interrupt () đã được gọi trên luồng), thì luồng cụ thể đó không thể chuyển sang chế độ ngủ. Nếu giấc ngủ được gọi trên đó, ngoại lệ bị gián đoạn được ném. Sau khi ném ngoại lệ một lần nữa cờ được đặt thành false.
  2. Nếu luồng đã ngủ và ngắt () được gọi, luồng sẽ thoát khỏi trạng thái ngủ và ném Ngoại lệ bị gián đoạn.

1

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


1

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


1

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.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.