Thread.sleep ของ Java จะโยน InterruptedException เมื่อใด


111

Thread.sleep ของ Java จะโยน InterruptedException เมื่อใด ปลอดภัยที่จะเพิกเฉยหรือไม่? ฉันไม่ได้ทำมัลติเธรดใด ๆ ฉันต้องการรอสักครู่ก่อนที่จะลองดำเนินการอีกครั้ง



1
ขึ้นอยู่กับความหมายที่คุณหมายถึง "ละเว้น" InterruptedExceptionเป็นข้อยกเว้นที่จับดังนั้นคุณจึงไม่สามารถรวบรวมจนกว่าคุณจะจัดการหรือประกาศประเภทของข้อยกเว้นนี้กับวิธีการใด ๆ ที่เข้าร่วมหรือหลับThreadหรือโทรบนwait() Object
8bitjunkie

คำตอบ:


41

โดยทั่วไปคุณไม่ควรเพิกเฉยต่อข้อยกเว้น ดูกระดาษต่อไปนี้:

อย่ากลืนสิ่งที่ขัดจังหวะ

บางครั้งการขว้าง InterruptedException ไม่ใช่ทางเลือกเช่นเมื่องานที่กำหนดโดย Runnable เรียกใช้วิธีการขัดจังหวะ ในกรณีนี้คุณไม่สามารถสร้าง InterruptedException ขึ้นมาใหม่ได้ แต่คุณไม่ต้องการทำอะไรเลย เมื่อวิธีการบล็อกตรวจพบการขัดจังหวะและพ่น InterruptedException จะเป็นการล้างสถานะที่ถูกขัดจังหวะ หากคุณตรวจจับ InterruptedException แต่ไม่สามารถสร้างใหม่ได้คุณควรเก็บรักษาหลักฐานที่แสดงว่ามีการขัดจังหวะเกิดขึ้นเพื่อให้โค้ดที่สูงขึ้นบน call stack สามารถเรียนรู้การหยุดชะงักและตอบสนองได้หากต้องการ งานนี้ทำได้โดยการเรียก interrupt () เพื่อ "reinterrupt" เธรดปัจจุบันดังที่แสดงใน Listing 3 อย่างน้อยที่สุดเมื่อใดก็ตามที่คุณจับ InterruptedException และไม่ต้องเปลี่ยนใหม่ให้ขัดจังหวะเธรดปัจจุบันใหม่ก่อนที่จะกลับมา

public class TaskRunner implements Runnable {
    private BlockingQueue<Task> queue;

    public TaskRunner(BlockingQueue<Task> queue) { 
        this.queue = queue; 
    }

    public void run() { 
        try {
             while (true) {
                 Task task = queue.take(10, TimeUnit.SECONDS);
                 task.execute();
             }
         }
         catch (InterruptedException e) { 
             // Restore the interrupted status
             Thread.currentThread().interrupt();
         }
    }
}

ดูเอกสารทั้งหมดที่นี่:

http://www.ibm.com/developerworks/java/library/j-jtp05236/index.html?ca=drs-


38

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

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

} catch (InterruptedException e) {
  Thread.currentThread().interrupt();
  // code for stopping current task so thread stops
}

ซึ่งตั้งค่าสถานะนั้นอีกครั้ง หลังจากนั้นเสร็จสิ้นการดำเนินการ นี่จะเป็นพฤติกรรมที่ถูกต้องแม้ไม่เคยใช้ยาก

สิ่งที่อาจจะดีกว่าคือเพิ่มสิ่งนี้:

} catch (InterruptedException e) {
  throw new RuntimeException("Unexpected interrupt", e);
}

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


5
ยืนยันในชวาเป็นปิดโดยปริยาย ดังนั้นจึงเป็นการดีกว่าที่จะโยนไฟล์RuntimeException.
Evgeni Sergeev

11

จดหมายข่าว Java Specialists (ซึ่งฉันสามารถแนะนำได้โดยไม่สงวนลิขสิทธิ์) มีบทความที่น่าสนใจเกี่ยวกับเรื่องนี้และวิธีจัดการกับไฟล์InterruptedException. ควรค่าแก่การอ่านและการย่อย


1
มันพูดว่าอะไร?
theonlygusti

5

วิธีการเช่นsleep()และwait()ชั้นเรียนThreadอาจทำให้InterruptedExceptionไฟล์. สิ่งนี้จะเกิดขึ้นหากบางคนthreadต้องการขัดขวางสิ่งthreadที่กำลังรอหรือนอนหลับ


3

วิธีที่ง่ายและมั่นคงในการจัดการกับโค้ดเธรดเดียวคือการจับและดึงกลับมาใหม่ใน RuntimeException เพื่อหลีกเลี่ยงความจำเป็นในการประกาศสำหรับทุกวิธี


-7

InterruptedExceptionมักจะถูกโยนทิ้งเมื่อถูกขัดจังหวะการนอนหลับ


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