ความแตกต่างระหว่างวิธีการจัดการ InterruptedException ต่อไปนี้คืออะไร วิธีที่ดีที่สุดที่จะทำคืออะไร?
คุณอาจมาถามคำถามนี้เพราะคุณเรียกวิธีการInterruptedExceptionหนึ่ง
ก่อนอื่นคุณควรเห็นthrows InterruptedExceptionว่ามันคืออะไร: ส่วนหนึ่งของวิธีการที่เป็นลายเซ็นและผลลัพธ์ที่เป็นไปได้ของการโทรวิธีที่คุณโทร ดังนั้นเริ่มต้นด้วยการยอมรับความจริงที่ว่าInterruptedExceptionเป็นผลที่สมบูรณ์แบบของการเรียกใช้เมธอด
ทีนี้ถ้าวิธีการที่คุณโทรมีข้อยกเว้นเช่นนั้นวิธีการของคุณควรทำอย่างไร? คุณสามารถหาคำตอบได้โดยคิดถึงสิ่งต่อไปนี้:
มันเหมาะสมสำหรับวิธีการที่คุณใช้ในการโยนInterruptedExceptionหรือไม่? สิ่งที่แตกต่างกันคือInterruptedExceptionผลลัพธ์ที่สมเหตุสมผลเมื่อเรียกใช้วิธีการของคุณ ?
ถ้าใช่แล้วthrows InterruptedExceptionควรเป็นส่วนหนึ่งของคุณลายเซ็นวิธีและคุณควรปล่อยให้การเผยแพร่ข้อยกเว้น (เช่นไม่จับมันเลย)
ตัวอย่าง : วิธีการของคุณรอค่าจากเครือข่ายเพื่อให้การคำนวณเสร็จสิ้นและส่งคืนผลลัพธ์ หากการบล็อกเครือข่ายโทรออกInterruptedExceptionวิธีการของคุณไม่สามารถคำนวณได้ตามปกติ คุณปล่อยให้การInterruptedExceptionเผยแพร่
int computeSum(Server server) throws InterruptedException {
// Any InterruptedException thrown below is propagated
int a = server.getValueA();
int b = server.getValueB();
return a + b;
}
ถ้าไม่เช่นนั้นคุณไม่ควรประกาศวิธีการของคุณด้วยthrows InterruptedExceptionและคุณควร (ต้อง!) ตรวจจับข้อยกเว้น ตอนนี้มีสองสิ่งที่สำคัญที่ต้องจำไว้ในสถานการณ์นี้:
มีคนขัดจังหวะชุดข้อความของคุณ อาจมีบางคนที่อยากจะยกเลิกการดำเนินการยกเลิกโปรแกรมอย่างสง่างามหรืออะไรก็ตาม คุณควรจะสุภาพกับใครคนนั้นและกลับมาจากวิธีการของคุณโดยไม่ต้องกังวลใจต่อไป
แม้ว่าวิธีการของคุณสามารถจัดการเพื่อสร้างมูลค่าส่งคืนที่เหมาะสมในกรณีInterruptedExceptionที่ความจริงที่ว่าเธรดถูกขัดจังหวะอาจยังคงมีความสำคัญ โดยเฉพาะอย่างยิ่งรหัสที่เรียกวิธีการของคุณอาจสนใจว่าเกิดการขัดจังหวะระหว่างการดำเนินการตามวิธีการของคุณหรือไม่ คุณควรบันทึกข้อเท็จจริงที่มีการหยุดชะงักโดยการตั้งค่าสถานะขัดจังหวะ:Thread.currentThread().interrupt()
ตัวอย่าง : ผู้ใช้ขอให้พิมพ์ผลรวมของสองค่า การพิมพ์ " Failed to compute sum" เป็นที่ยอมรับได้หากไม่สามารถคำนวณผลรวมได้ (และดีกว่าปล่อยให้โปรแกรมขัดข้องด้วยการติดตามสแต็กเนื่องจากการInterruptedException) ในคำอื่น ๆ ก็ไม่ได้throws InterruptedExceptionทำให้ความรู้สึกที่จะประกาศวิธีการนี้ด้วย
void printSum(Server server) {
try {
int sum = computeSum(server);
System.out.println("Sum: " + sum);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // set interrupt flag
System.out.println("Failed to compute sum");
}
}
โดยตอนนี้มันควรจะชัดเจนว่าการทำเพียงแค่throw new RuntimeException(e)เป็นความคิดที่ไม่ดี มันไม่สุภาพมากสำหรับผู้โทร คุณสามารถคิดค้นข้อยกเว้นรันไทม์ใหม่ แต่สาเหตุที่แท้จริง (บางคนต้องการให้เธรดหยุดการทำงาน) อาจหายไป
ตัวอย่างอื่น ๆ :
การนำไปใช้Runnable : อย่างที่คุณอาจค้นพบลายเซ็นของRunnable.runไม่อนุญาตให้ทำการทำInterruptedExceptionsใหม่ ดีที่คุณลงทะเบียนในการใช้Runnableซึ่งหมายความว่าคุณInterruptedExceptionsได้ลงทะเบียนเพื่อจัดการกับความเป็นไปได้ เลือกอินเทอร์เฟซอื่นเช่นCallableหรือทำตามวิธีที่สองด้านบน
การโทรThread.sleep : คุณกำลังพยายามอ่านไฟล์และข้อมูลจำเพาะระบุว่าคุณควรลอง 10 ครั้งโดยใช้เวลา 1 วินาที คุณโทรThread.sleep(1000)มา InterruptedExceptionดังนั้นคุณจำเป็นต้องจัดการกับ สำหรับวิธีการเช่นtryToReadFileมันทำให้รู้สึกดีที่จะพูดว่า"ถ้าฉันขัดจังหวะฉันไม่สามารถดำเนินการของฉันพยายามที่จะอ่านไฟล์" ในคำอื่น ๆ InterruptedExceptionsก็จะทำให้ความรู้สึกที่สมบูรณ์แบบสำหรับวิธีการโยน
String tryToReadFile(File f) throws InterruptedException {
for (int i = 0; i < 10; i++) {
if (f.exists())
return readFile(f);
Thread.sleep(1000);
}
return null;
}
โพสต์นี้ได้รับการเขียนใหม่เป็นบทความที่นี่