java.lang.Thread.interrupt () ทำอะไร


คำตอบ:


250

Thread.interrupt()ตั้งค่าสถานะ / สถานะที่ถูกขัดจังหวะของเธรดเป้าหมาย จากนั้นโค้ดที่รันในเธรดเป้าหมายนั้นอาจสำรวจสถานะที่ถูกขัดจังหวะและจัดการอย่างเหมาะสม วิธีการบางอย่างที่บล็อกเช่นObject.wait()อาจใช้สถานะขัดจังหวะทันทีและโยนข้อยกเว้นที่เหมาะสม (ปกติInterruptedException)

การขัดจังหวะใน Java ไม่ได้เป็นการจองล่วงหน้า ใส่อีกวิธีหนึ่งที่ทั้งสองเธรดต้องร่วมมือเพื่อดำเนินการขัดจังหวะอย่างถูกต้อง หากเธรดเป้าหมายไม่ได้สำรวจสถานะการขัดจังหวะการขัดจังหวะจะถูกละเว้นอย่างมีประสิทธิภาพ

การสำรวจเกิดขึ้นผ่านThread.interrupted()วิธีการที่ส่งคืนสถานะขัดจังหวะของเธรดปัจจุบันและล้างการตั้งค่าสถานะอินเตอร์รัปต์นั้น โดยทั่วไปแล้วเธรดอาจทำอะไรบางอย่างเช่นการขัดจังหวะการขัดจังหวะ

แก้ไข (จากความคิดเห็น Thilo): บางวิธีของ API ได้สร้างขึ้นในการจัดการอินเตอร์รัปต์ ในส่วนบนของหัวของฉันนี้รวมถึง

  • Object.wait(), Thread.sleep()และThread.join()
  • java.util.concurrentโครงสร้างส่วนใหญ่
  • Java NIO ( แต่ไม่ java.io) และมันก็ไม่ได้ใช้แทนการใช้InterruptedExceptionClosedByInterruptException

แก้ไข (จากคำตอบของ@ thomas-porninสำหรับคำถามเดียวกันเพื่อความสมบูรณ์)

การขัดจังหวะของเธรดเป็นวิธีอ่อนโยนในการเขยิบเธรด มันถูกใช้เพื่อให้เธรดมีโอกาสที่จะออกอย่างหมดจดเมื่อเทียบกับThread.stop()ที่เป็นมากกว่าการยิงเธรดด้วยปืนไรเฟิลจู่โจม


22
โปรดทราบว่าวิธีการเช่นการนอนหลับหรือรอทำแบบสำรวจนี้และโยน InterruptedException ด้วยตนเอง
Thilo

1
หากคุณกำลังใช้ไฟล์ขัดจังหวะ I / O เอฟเฟกต์จะไม่สุภาพเท่านี้ โดยทั่วไปคุณจะได้รับไฟล์เสียหาย
Marko Topolnik

หากคุณพูดถึง Thread.interrupted ดูเหมือนว่าควรมีการกล่าวถึงว่ามีการตั้งค่าสถานะ Thread.isInterrupted เช่นกันซึ่งไม่ได้ล้างค่าสถานะซึ่งทำให้เหมาะสำหรับนักพัฒนาแอปพลิเคชัน
Nathan Hughes

67

ขัดจังหวะคืออะไร

การขัดจังหวะเป็นการบ่งชี้เธรดที่ควรหยุดสิ่งที่ทำและทำอย่างอื่น ขึ้นอยู่กับโปรแกรมเมอร์ที่จะตัดสินใจว่าเธรดตอบสนองต่อการขัดจังหวะได้อย่างไร แต่เป็นเรื่องปกติที่เธรดจะจบการทำงาน

มันใช้งานอย่างไร?

กลไกการขัดจังหวะถูกนำมาใช้โดยใช้การตั้งค่าสถานะภายในที่เรียกว่าสถานะการขัดจังหวะ การเรียกใช้ Thread.interrupt จะตั้งค่าสถานะนี้ เมื่อเธรดตรวจสอบการขัดจังหวะโดยเรียกใช้เมธอดแบบคงที่ Thread.interrupted สถานะการขัดจังหวะจะถูกล้าง Thread.isInterrupted แบบไม่คงที่ซึ่งใช้โดยเธรดหนึ่งเพื่อสอบถามสถานะการขัดจังหวะของอีกรายการหนึ่งจะไม่เปลี่ยนสถานะการขัดจังหวะ

อ้างอิงจากThread.interrupt()API :

ขัดจังหวะเธรดนี้ ก่อนอื่นให้เรียกใช้เมธอด checkAccess ของเธรดนี้ซึ่งอาจทำให้โยน SecurityException

หากเธรดนี้ถูกบล็อกในการเรียกใช้การรอ () รอ (ยาว) หรือวิธีการรอ (ยาว, int) ของคลาสวัตถุหรือการเข้าร่วม (), เข้าร่วม (ยาว), เข้าร่วม (ยาว, int) , sleep (long) หรือ sleep (long, int), เมธอดของคลาสนี้จากนั้นสถานะการขัดจังหวะของมันจะถูกล้างออกและมันจะได้รับ InterruptException

หากเธรดนี้ถูกบล็อกในการดำเนินการ I / O บนช่องสัญญาณขัดจังหวะช่องสัญญาณจะถูกปิดสถานะการขัดจังหวะของเธรดจะถูกตั้งค่าและเธรดจะได้รับ ClosedByInterruptException

หากเธรดนี้ถูกบล็อกในตัวเลือกสถานะการขัดจังหวะของเธรดจะถูกตั้งค่าและจะส่งคืนทันทีจากการดำเนินการเลือกอาจเป็นไปได้ด้วยค่าที่ไม่เป็นศูนย์เช่นเดียวกับวิธีการปลุกของตัวเลือกที่ถูกเรียกใช้

หากไม่มีเงื่อนไขก่อนหน้านี้ค้างไว้สถานะขัดจังหวะของเธรดนี้จะถูกตั้งค่า

ลองดูสิ่งนี้เพื่อความเข้าใจที่สมบูรณ์เกี่ยวกับสิ่งเดียวกัน:

http://download.oracle.com/javase/tutorial/essential/concurrency/interrupt.html


นี่คือการเชื่อฟังคำอธิบายบางส่วน นอกจากนี้ยังขัดจังหวะวิธีการขัดจังหวะ
มาร์ควิสแห่ง Lorne

@EJP คำถามนี้เกี่ยวกับเมธอด Thread.interrupt () คืออะไรและทำงานอย่างไร ฉันคิดว่าอะไรก็ตามที่ฉันโพสต์พร้อมลิงค์ตอบคำถามที่ถาม ฉันยังไม่เข้าใจสิ่งที่คุณต้องการใช่ไหม
YoK

ฉันขอให้คุณแก้ไขคำสั่งที่ไม่ถูกต้องบางส่วนของคุณว่ามีการใช้งานโดยแฟล็ก นั่นเป็นเพียงส่วนหนึ่งของเรื่องราว ดูเหมือนว่าฉันจะค่อนข้างชัดเจน
มาร์ควิสแห่ง Lorne

@EJP ขอบคุณ ตอนนี้ฉันเข้าใจสิ่งที่คุณพูด ฉันได้อัปเดตคำตอบและเพิ่มเอกสาร API สำหรับวิธีการแล้ว นี้ครอบคลุมส่วนวิธีการขัดจังหวะซึ่งหายไปจากคำตอบของฉัน หวังว่าคำตอบของฉันจะเสร็จสมบูรณ์ในตอนนี้ :)
YoK

13

หากเธรดเป้าหมายกำลังรออยู่ (โดยการโทรwait()หรือวิธีการอื่นที่เกี่ยวข้องที่ทำสิ่งเดียวกันเช่นsleep()) มันจะถูกขัดจังหวะซึ่งหมายความว่ามันจะหยุดรอสิ่งที่รอและรับ InterruptException แทน

มันขึ้นอยู่กับเธรดอย่างสมบูรณ์ (โค้ดที่เรียกว่าwait()) เพื่อตัดสินใจว่าจะทำอย่างไรในสถานการณ์นี้ มันไม่ได้ยุติเธรดโดยอัตโนมัติ

บางครั้งก็ใช้ร่วมกับการตั้งค่าสถานะการเลิกจ้าง เมื่อถูกขัดจังหวะเธรดสามารถตรวจสอบการตั้งค่าสถานะนี้และจากนั้นปิดตัวลง แต่อีกครั้งนี่เป็นเพียงการประชุม


อายุ 9 ขวบคำตอบที่อมตะ! +1
snr

10

เพื่อความสมบูรณ์นอกเหนือจากคำตอบอื่น ๆหากเธรดถูกขัดจังหวะก่อนที่จะบล็อกObject.wait(..)หรือThread.sleep(..)เป็นต้นสิ่งนี้จะเทียบเท่ากับการถูกขัดจังหวะทันทีเมื่อปิดกั้นวิธีดังกล่าวดังตัวอย่างต่อไปนี้แสดง

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");
    }
}

เอาท์พุท:

$ 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

ความหมาย: ถ้าคุณวนลูปเหมือนดังต่อไปนี้และการขัดจังหวะเกิดขึ้นในช่วงเวลาที่แน่นอนเมื่อการควบคุมได้ออกไปThread.sleep(..)และกำลังไปรอบ ๆ วงข้อยกเว้นจะยังคงเกิดขึ้น ดังนั้นจึงปลอดภัยอย่างสมบูรณ์ที่จะพึ่งพา InterruptedException ที่ถูกโยนไปอย่างน่าเชื่อถือหลังจากที่เธรดถูกขัดจังหวะ :

while (true) {
    try {
        Thread.sleep(10);
    } catch (InterruptedException ie) {
        break;
    }
}

4

Thread.interrupt()ตั้งค่าสถานะ / สถานะที่ถูกขัดจังหวะของเธรดเป้าหมายเป็นจริงซึ่งเมื่อการตรวจสอบโดยใช้Thread.interrupted()สามารถช่วยในการหยุดเธรดที่ไม่มีที่สิ้นสุด อ้างอิงhttp://www.yegor256.com/2015/10/20/interrupted-exception.html


4

การหยุดชะงักของกระทู้จะขึ้นอยู่กับธงสถานะการขัดจังหวะ สำหรับค่าเริ่มต้นทุกด้ายสถานะขัดจังหวะถูกตั้งค่าเป็นเท็จ เมื่อใดก็ตามที่ขัดจังหวะ ()วิธีการที่เรียกว่าในหัวข้อสถานะขัดจังหวะถูกตั้งค่าให้เป็นจริง

  1. หากสถานะขัดจังหวะ = true (ขัดจังหวะ () เรียกใช้แล้วบนเธรด) เธรดเฉพาะนั้นไม่สามารถเข้าสู่โหมดสลีปได้ หากการนอนหลับถูกเรียกใช้บนเธรดที่ขัดจังหวะข้อยกเว้นจะถูกส่งออกไป หลังจากโยนข้อยกเว้นอีกครั้งตั้งค่าสถานะเป็นเท็จ
  2. หากเธรดนอนหลับแล้วและอินเตอร์รัปต์ ()ถูกเรียกใช้เธรดจะออกจากโหมดสลีปและโยนข้อยกเว้นขัดจังหวะ

1

โมฆะสาธารณะขัดจังหวะ ()

ขัดจังหวะเธรดนี้

ยกเว้นว่าเธรดปัจจุบันกำลังขัดจังหวะตัวเองซึ่งได้รับอนุญาตเสมอเมธอด checkAccess ของเธรดนี้จะถูกเรียกใช้ซึ่งอาจทำให้โยน SecurityException

หากเธรดนี้ถูกบล็อกในการเรียกใช้การรอ () รอ (ยาว) หรือวิธีการรอ (ยาว, int) ของคลาสวัตถุหรือการเข้าร่วม (), เข้าร่วม (ยาว), เข้าร่วม (ยาว, int) , sleep (long) หรือ sleep (long, int), เมธอดของคลาสนี้จากนั้นสถานะการขัดจังหวะของมันจะถูกล้างออกและมันจะได้รับ InterruptException

หากเธรดนี้ถูกบล็อกในการดำเนินการ I / O บนช่องสัญญาณขัดจังหวะช่องสัญญาณจะถูกปิดสถานะการขัดจังหวะของเธรดจะถูกตั้งค่าและเธรดจะได้รับ ClosedByInterruptException

หากเธรดนี้ถูกบล็อกในตัวเลือกสถานะการขัดจังหวะของเธรดจะถูกตั้งค่าและจะส่งคืนทันทีจากการดำเนินการเลือกอาจเป็นไปได้ด้วยค่าที่ไม่เป็นศูนย์เช่นเดียวกับวิธีการปลุกของตัวเลือกที่ถูกเรียกใช้

หากไม่มีเงื่อนไขก่อนหน้านี้ค้างไว้สถานะขัดจังหวะของเธรดนี้จะถูกตั้งค่า

การขัดจังหวะเธรดที่ไม่มีชีวิตไม่จำเป็นต้องมีผลกระทบใด ๆ

พ่น: SecurityException - ถ้าเธรดปัจจุบันไม่สามารถแก้ไขเธรดนี้ได้


1

การขัดจังหวะเป็นการบ่งชี้เธรดที่ควรหยุดสิ่งที่ทำและทำอย่างอื่น ขึ้นอยู่กับโปรแกรมเมอร์ที่จะตัดสินใจว่าเธรดตอบสนองอย่างไรต่ออินเทอร์รัปต์ แต่มันเป็นเรื่องธรรมดามากที่เธรดจะยุติ การอ้างอิงที่ดีมาก: https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html


1

Thread.interrupt () วิธีการตั้งค่าสถานะ 'สถานะขัดจังหวะ' ภายใน โดยปกติแล้วการตั้งค่าสถานะนั้นจะถูกตรวจสอบโดยวิธีการ Thread.interrupted ()

ตามระเบียบวิธีการใด ๆ ที่มีอยู่ผ่าน InterruptedException ต้องล้างการตั้งค่าสถานะการขัดจังหวะ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.