ใครเป็นคนเรียกเมธอด Java Thread interrupt () ถ้าฉันไม่ใช่


87

ฉันได้อ่านและอ่าน Java Concurrency in Practice อีกครั้งฉันได้อ่านหัวข้อต่างๆที่นี่ในหัวข้อนี้ฉันได้อ่านบทความของ IBM เกี่ยวกับการจัดการกับ InterruptedExceptionและยังมีบางอย่างที่ฉันไม่เข้าใจซึ่งฉันคิดว่าอาจเสียได้ แบ่งออกเป็นสองคำถาม:

  1. ถ้าฉันไม่เคยรบกวนหัวข้ออื่น ๆ ตัวเองสิ่งที่สามารถเรียกInterruptedException ?

  2. ถ้าฉันไม่เคยรบกวนหัวข้ออื่น ๆ ด้วยตัวเองโดยใช้ขัดจังหวะ () (พูดเพราะผมใช้วิธีการอื่นในการยกเลิกหัวข้อการทำงานของฉันเช่นยาพิษและในขณะที่ (! ยกเลิก)ห่วงสไตล์ [ขณะที่ทั้งสองได้อธิบายไว้ใน Jcip]) สิ่งที่ ไม่InterruptedExceptionนั้นหมายความว่าอย่างไร ฉันควรทำอย่างไรเมื่อจับได้ ปิดแอพของฉันไหม

คำตอบ:


51

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

ในทางปฏิบัติกรณีการใช้งานปกติสำหรับinterrupt()กรอบงานบางประเภทหรือผู้จัดการบอกให้ผู้ปฏิบัติงานบางคนหยุดสิ่งที่พวกเขากำลังทำอยู่ หากเธรดของผู้ปฏิบัติงาน "ทราบการขัดจังหวะ" จะสังเกตได้ว่ามีการขัดจังหวะผ่านข้อยกเว้นหรือโดยการตรวจสอบแฟล็กถูกขัดจังหวะเป็นระยะ เมื่อสังเกตเห็นว่ามีการขัดจังหวะเธรดที่มีพฤติกรรมดีจะละทิ้งสิ่งที่กำลังทำอยู่และสิ้นสุดลง

สมมติว่าใช้กรณีข้างต้นโค้ดของคุณน่าจะถูกขัดจังหวะหากรันภายในกรอบงาน Java หรือจากเธรดผู้ปฏิบัติงานบางส่วน และเมื่อถูกขัดจังหวะโค้ดของคุณควรละทิ้งสิ่งที่กำลังทำอยู่และทำให้ตัวมันเองจบลงด้วยวิธีการที่เหมาะสมที่สุด ขึ้นอยู่กับวิธีการเรียกรหัสของคุณสิ่งนี้อาจทำได้โดยการส่งคืนหรือโดยทิ้งข้อยกเว้นที่เหมาะสม แต่มันคงไม่ควรโทรSystem.exit(). (แอปพลิเคชันของคุณไม่จำเป็นต้องทราบว่าเหตุใดจึงถูกขัดจังหวะและแน่นอนว่าไม่ทราบว่ามีเธรดอื่นที่ต้องถูกขัดจังหวะโดยเฟรมเวิร์กหรือไม่)

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


1) ถ้าฉันไม่เคยขัดจังหวะเธรดอื่น ๆ ด้วยตัวเองอะไรจะทำให้เกิด InterruptedException ได้

ตัวอย่างหนึ่งคือถ้าRunnableอ็อบเจ็กต์ของคุณถูกเรียกใช้งานโดยใช้ExecutorServiceและshutdownNow()ถูกเรียกใช้บริการ และตามทฤษฎีแล้วเธรดพูลของบุคคลที่สามหรือเฟรมเวิร์กการจัดการเธรดสามารถทำสิ่งนี้ได้อย่างถูกต้อง

2) ถ้าฉันไม่เคยขัดจังหวะเธรดอื่น ๆ ด้วยตัวเองโดยใช้ interrupt () ... InterruptedExceptionแล้วหมายความว่าอย่างไร? ฉันควรทำอย่างไรเมื่อจับได้ ปิดแอพของฉันไหม

คุณต้องวิเคราะห์ codebase เพื่อดูว่าinterrupt()โทรออกอะไรและทำไม เมื่อคุณคิดได้แล้วคุณสามารถหาสิ่งที่ >> ส่วน << ของแอปต้องทำ

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

3) ฉันจะรู้ได้อย่างไรว่าใครโทรมาinterrupt()?

ไม่มีคำตอบที่ดีสำหรับเรื่องนี้ สิ่งที่ดีที่สุดที่ฉันสามารถแนะนำได้คือตั้งค่าเบรกพอยต์Thread.interrupt()และดูที่กลุ่มการโทร


12

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

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


ฉันคิดว่าแค่ shutdownNow เรียกว่า interrupt () method การปิดเครื่องจริงหรือไม่
Harinder

9

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

อย่างไรก็ตามคุณไม่ควรปฏิบัติต่อInterruptedExceptionคนเดียวเป็น "คำสั่งเลิก" แต่คุณควรคิดว่าการขัดจังหวะเป็นเครื่องมือในการควบคุมสถานะการทำงานของเธรดในลักษณะเดียวกับที่Object.notify()ทำ ในลักษณะเดียวกับที่คุณตรวจสอบสถานะปัจจุบันหลังจากตื่นจากการโทรไปObject.wait()(คุณไม่คิดว่าการปลุกระบบหมายความว่าเงื่อนไขการรอของคุณเป็นที่พอใจแล้ว) หลังจากถูกสะกิดด้วยการขัดจังหวะคุณควรตรวจสอบว่าเหตุใดคุณจึงถูกขัดจังหวะ . โดยปกติจะมีวิธีการทำดังนี้ ตัวอย่างเช่นjava.util.concurrent.FutureTaskมีisCancelled()วิธีการ

ตัวอย่างโค้ด:

public void run() {
    ....
    try {
        .... // Calls that may block.
    } catch (InterruptedException e) {
        if (!running) {  // Add preferred synchronization here.
            return; // Explicit flag says we should stop running.
        }
        // We were interrupted, but the flag says we're still running.
        // It would be wrong to always exit here. The interrupt 'nudge'
        // could mean something completely different. For example, it
        // could be that the thread was blocking on a read from a particular
        // file, and now we should read from a different file.
        // Interrupt != quit (not necessarily).
    }
    ....
}
public void stop() {
    running = false; // Add preferred synchronization here.
    myThread.interrupt();
}

3

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

การขัดจังหวะที่ไม่คาดคิดที่อาจเกิดขึ้นจาก JRE คืองานที่ยกเลิกjava.util.concurrentและปิดแอพเพล็ต

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


สวัสดีทอมฉันจำชื่อคุณได้จาก cljp;) แน่นอน: ฉันไม่เคยต้องใช้interrupt () ด้วยตัวเอง ... เว้นแต่ฉันจะจับ InterruptedException และต้องการยืนยันสถานะที่ถูกขัดจังหวะอีกครั้ง แต่ยังไม่ 100% ชัดเจนสำหรับฉัน ฉันเป็นคนใหม่ที่นี่และรู้สึกประหลาดใจกับจำนวนโหวตและคำตอบ / ความคิดเห็น (ทั้งคนที่ถูกต้องและคนที่ผิด) เห็นได้ชัดว่ามันเป็นเรื่องที่ไม่สำคัญหรืออย่างน้อยก็มักจะอธิบายได้ไม่ดี ที่กล่าวว่าต้องขอบคุณทุกโพสต์ฉันเริ่มเห็นภาพชัดเจนขึ้นว่าเกิดอะไรขึ้น :)
SyntaxT3rr0r

3

คุณสามารถเรียนรู้สิ่งนี้ได้โดยการสร้างคลาสเธรดของคุณเอง (การขยายjava.lang.Thread) และinterrupt()วิธีการแทนที่ซึ่งคุณบันทึก stacktrace ลงในฟิลด์ String จากนั้นโอนไปยัง super.interrupt ()

public class MyThread extends Thread {

    public volatile String interruptStacktrace; // Temporary field for debugging purpose.

    @Override
    public void interrupt() {
        interruptStacktrace = dumpStack(); // You implement it somehow...

        super.interrupt();
    }
}

1

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


1

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

ถ้าฉันไม่เคยรบกวนหัวข้ออื่น ๆ ตัวเองสิ่งที่สามารถเรียกInterruptedException ?

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

มีหลายวิธีที่อาจมีการหยุดชะงักอาจหมดเวลาการขัดจังหวะ JVM เป็นต้น

ถ้าฉันไม่เคยขัดจังหวะเธรดอื่น ๆ ด้วยตัวเองโดยใช้การขัดจังหวะ () (พูดเพราะฉันใช้วิธีอื่นในการยกเลิกเธรดการทำงานของฉันเช่นยาพิษและในขณะที่ (! ยกเลิก) สไตล์ลูป [ตามที่อธิบายไว้ใน JCIP]) อะไร InterruptedException หมายความว่าอย่างไร ฉันควรทำอย่างไรเมื่อจับได้ ปิดแอพของฉันไหม

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

หวังว่านี่จะช่วยได้


0

คำInterruptedExceptionกล่าวที่ว่ากิจวัตรประจำวันอาจถูกขัดจังหวะ แต่ไม่จำเป็นว่าจะเป็นเช่นนั้น

หากคุณไม่คาดหวังว่าจะมีการขัดจังหวะคุณควรปฏิบัติเช่นเดียวกับข้อยกเว้นที่ไม่คาดคิด หากอยู่ในส่วนที่สำคัญซึ่งข้อยกเว้นที่ไม่คาดคิดอาจส่งผลร้ายตามมาทางที่ดีควรลองล้างทรัพยากรและปิดระบบอย่างสง่างาม (เนื่องจากได้รับสัญญาณขัดจังหวะซึ่งแอปพลิเคชันที่ได้รับการออกแบบมาอย่างดีซึ่งไม่ต้องพึ่งพาการขัดจังหวะ ในแบบที่ไม่ได้ออกแบบมาและต้องมีบางอย่างผิดปกติ) หรือหากรหัสที่เป็นปัญหาเป็นสิ่งที่ไม่สำคัญหรือไม่สำคัญคุณอาจต้องละเว้น (หรือบันทึก) การขัดจังหวะและดำเนินการต่อ

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