คุณช่วยอธิบายว่าjava.lang.Thread.interrupt()
เมื่อไหร่ที่เรียกใช้?
คุณช่วยอธิบายว่าjava.lang.Thread.interrupt()
เมื่อไหร่ที่เรียกใช้?
คำตอบ:
Thread.interrupt()
ตั้งค่าสถานะ / สถานะที่ถูกขัดจังหวะของเธรดเป้าหมาย จากนั้นโค้ดที่รันในเธรดเป้าหมายนั้นอาจสำรวจสถานะที่ถูกขัดจังหวะและจัดการอย่างเหมาะสม วิธีการบางอย่างที่บล็อกเช่นObject.wait()
อาจใช้สถานะขัดจังหวะทันทีและโยนข้อยกเว้นที่เหมาะสม (ปกติInterruptedException
)
การขัดจังหวะใน Java ไม่ได้เป็นการจองล่วงหน้า ใส่อีกวิธีหนึ่งที่ทั้งสองเธรดต้องร่วมมือเพื่อดำเนินการขัดจังหวะอย่างถูกต้อง หากเธรดเป้าหมายไม่ได้สำรวจสถานะการขัดจังหวะการขัดจังหวะจะถูกละเว้นอย่างมีประสิทธิภาพ
การสำรวจเกิดขึ้นผ่านThread.interrupted()
วิธีการที่ส่งคืนสถานะขัดจังหวะของเธรดปัจจุบันและล้างการตั้งค่าสถานะอินเตอร์รัปต์นั้น โดยทั่วไปแล้วเธรดอาจทำอะไรบางอย่างเช่นการขัดจังหวะการขัดจังหวะ
แก้ไข (จากความคิดเห็น Thilo): บางวิธีของ API ได้สร้างขึ้นในการจัดการอินเตอร์รัปต์ ในส่วนบนของหัวของฉันนี้รวมถึง
Object.wait()
, Thread.sleep()
และThread.join()
java.util.concurrent
โครงสร้างส่วนใหญ่InterruptedException
ClosedByInterruptException
แก้ไข (จากคำตอบของ@ thomas-porninสำหรับคำถามเดียวกันเพื่อความสมบูรณ์)
การขัดจังหวะของเธรดเป็นวิธีอ่อนโยนในการเขยิบเธรด มันถูกใช้เพื่อให้เธรดมีโอกาสที่จะออกอย่างหมดจดเมื่อเทียบกับThread.stop()
ที่เป็นมากกว่าการยิงเธรดด้วยปืนไรเฟิลจู่โจม
ขัดจังหวะคืออะไร
การขัดจังหวะเป็นการบ่งชี้เธรดที่ควรหยุดสิ่งที่ทำและทำอย่างอื่น ขึ้นอยู่กับโปรแกรมเมอร์ที่จะตัดสินใจว่าเธรดตอบสนองต่อการขัดจังหวะได้อย่างไร แต่เป็นเรื่องปกติที่เธรดจะจบการทำงาน
มันใช้งานอย่างไร?
กลไกการขัดจังหวะถูกนำมาใช้โดยใช้การตั้งค่าสถานะภายในที่เรียกว่าสถานะการขัดจังหวะ การเรียกใช้ 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
หากเธรดเป้าหมายกำลังรออยู่ (โดยการโทรwait()
หรือวิธีการอื่นที่เกี่ยวข้องที่ทำสิ่งเดียวกันเช่นsleep()
) มันจะถูกขัดจังหวะซึ่งหมายความว่ามันจะหยุดรอสิ่งที่รอและรับ InterruptException แทน
มันขึ้นอยู่กับเธรดอย่างสมบูรณ์ (โค้ดที่เรียกว่าwait()
) เพื่อตัดสินใจว่าจะทำอย่างไรในสถานการณ์นี้ มันไม่ได้ยุติเธรดโดยอัตโนมัติ
บางครั้งก็ใช้ร่วมกับการตั้งค่าสถานะการเลิกจ้าง เมื่อถูกขัดจังหวะเธรดสามารถตรวจสอบการตั้งค่าสถานะนี้และจากนั้นปิดตัวลง แต่อีกครั้งนี่เป็นเพียงการประชุม
เพื่อความสมบูรณ์นอกเหนือจากคำตอบอื่น ๆหากเธรดถูกขัดจังหวะก่อนที่จะบล็อก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;
}
}
Thread.interrupt()
ตั้งค่าสถานะ / สถานะที่ถูกขัดจังหวะของเธรดเป้าหมายเป็นจริงซึ่งเมื่อการตรวจสอบโดยใช้Thread.interrupted()
สามารถช่วยในการหยุดเธรดที่ไม่มีที่สิ้นสุด อ้างอิงhttp://www.yegor256.com/2015/10/20/interrupted-exception.html
การหยุดชะงักของกระทู้จะขึ้นอยู่กับธงสถานะการขัดจังหวะ สำหรับค่าเริ่มต้นทุกด้ายสถานะขัดจังหวะถูกตั้งค่าเป็นเท็จ เมื่อใดก็ตามที่ขัดจังหวะ ()วิธีการที่เรียกว่าในหัวข้อสถานะขัดจังหวะถูกตั้งค่าให้เป็นจริง
โมฆะสาธารณะขัดจังหวะ ()
ขัดจังหวะเธรดนี้
ยกเว้นว่าเธรดปัจจุบันกำลังขัดจังหวะตัวเองซึ่งได้รับอนุญาตเสมอเมธอด checkAccess ของเธรดนี้จะถูกเรียกใช้ซึ่งอาจทำให้โยน SecurityException
หากเธรดนี้ถูกบล็อกในการเรียกใช้การรอ () รอ (ยาว) หรือวิธีการรอ (ยาว, int) ของคลาสวัตถุหรือการเข้าร่วม (), เข้าร่วม (ยาว), เข้าร่วม (ยาว, int) , sleep (long) หรือ sleep (long, int), เมธอดของคลาสนี้จากนั้นสถานะการขัดจังหวะของมันจะถูกล้างออกและมันจะได้รับ InterruptException
หากเธรดนี้ถูกบล็อกในการดำเนินการ I / O บนช่องสัญญาณขัดจังหวะช่องสัญญาณจะถูกปิดสถานะการขัดจังหวะของเธรดจะถูกตั้งค่าและเธรดจะได้รับ ClosedByInterruptException
หากเธรดนี้ถูกบล็อกในตัวเลือกสถานะการขัดจังหวะของเธรดจะถูกตั้งค่าและจะส่งคืนทันทีจากการดำเนินการเลือกอาจเป็นไปได้ด้วยค่าที่ไม่เป็นศูนย์เช่นเดียวกับวิธีการปลุกของตัวเลือกที่ถูกเรียกใช้
หากไม่มีเงื่อนไขก่อนหน้านี้ค้างไว้สถานะขัดจังหวะของเธรดนี้จะถูกตั้งค่า
การขัดจังหวะเธรดที่ไม่มีชีวิตไม่จำเป็นต้องมีผลกระทบใด ๆ
พ่น: SecurityException - ถ้าเธรดปัจจุบันไม่สามารถแก้ไขเธรดนี้ได้
การขัดจังหวะเป็นการบ่งชี้เธรดที่ควรหยุดสิ่งที่ทำและทำอย่างอื่น ขึ้นอยู่กับโปรแกรมเมอร์ที่จะตัดสินใจว่าเธรดตอบสนองอย่างไรต่ออินเทอร์รัปต์ แต่มันเป็นเรื่องธรรมดามากที่เธรดจะยุติ การอ้างอิงที่ดีมาก: https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html
Thread.interrupt () วิธีการตั้งค่าสถานะ 'สถานะขัดจังหวะ' ภายใน โดยปกติแล้วการตั้งค่าสถานะนั้นจะถูกตรวจสอบโดยวิธีการ Thread.interrupted ()
ตามระเบียบวิธีการใด ๆ ที่มีอยู่ผ่าน InterruptedException ต้องล้างการตั้งค่าสถานะการขัดจังหวะ