ในบทความนี้เราจะพูดคุยเกี่ยวกับกลไกการขัดจังหวะการขัดจังหวะของเธรดกระทู้ Java
กระทู้ขัดจังหวะ
เมธอด Thread.Interrupt () ของเธรดคือการขัดจังหวะเธรด มันจะตั้งค่าบิตสถานะอินเตอร์รัปต์ของเธรดนั่นคือตั้งค่าเป็น TRUE ไม่ว่าเธรดที่ถูกขัดจังหวะจะตายรองานใหม่หรือดำเนินการต่อไปยังขั้นตอนต่อไปขึ้นอยู่กับโปรแกรมเอง เธรดจะตรวจจับธงขัดจังหวะนี้เป็นครั้งคราวเพื่อตรวจสอบว่าควรขัดจังหวะเธรดหรือไม่ (ไม่ว่าธงขัดจังหวะจะเป็นจริงหรือไม่) มันไม่ได้ขัดจังหวะเธรดที่ทำงานเช่นวิธีการหยุด
ตรวจสอบว่าเธรดถูกขัดจังหวะหรือไม่
ในการตรวจสอบว่าเธรดได้ส่งคำขอขัดจังหวะหรือไม่โปรดใช้ Thread.currentThread (). วิธีการ isinterrupted () (เพราะมันจะไม่ล้างบิตอินเตอร์รัปต์ธงทันทีหลังจากตั้งค่าบิตอินเตอร์รัปต์ของเธรดให้เป็นจริงนั่นคือมันจะไม่ตั้งค่าสถานะอินเตอร์รัปต์เป็นเท็จ) อย่าใช้เมธอด thread.interrupted () (บิตอินเตอร์รัปต์ธงจะถูกล้างหลังจากวิธีการที่เรียกว่านั่นคือรีเซ็ตเป็นเท็จ) วิธีการตัดสิน ต่อไปนี้เป็นวิธีการขัดจังหวะของเธรดเมื่ออยู่ในลูป:
ในขณะที่ (! thread.currentthread (). isinterrupted () && ทำงานเพิ่มเติม) {ทำงานเพิ่มเติม}ธงสถานะอินเตอร์รัปต์
มีวิธีการต่อไปนี้ในกลไกการขัดจังหวะการขัดจังหวะ:
ดังนั้นกลไกการขัดจังหวะการขัดจังหวะไม่ได้ขัดจังหวะเธรดปัจจุบัน แต่การเปลี่ยนแปลงในมาร์กอัปอินเตอร์รัปต์ ลองทดสอบด้วยตัวอย่างก่อน
คลาสสาธารณะ interrupttest {// เวลาที่ใช้ที่นี่ใช้ในการพิมพ์เวลาคงที่ส่วนตัวเป็นเวลานาน = 0; Void retemime ส่วนตัวคงที่ () {time = system.currentTimeMillis (); } โมฆะคงที่ส่วนตัว printContent (เนื้อหาสตริง) {system.out.println (เนื้อหา + "เวลา:" + (System.currentTimeMillis () - เวลา)); } โมฆะคงที่สาธารณะหลัก (สตริง [] args) {test1 (); } โมฆะคงที่ส่วนตัว test1 () {thread1 thread1 = thread1 () ใหม่ (); Thread1.start (); // ขัดจังหวะการขัดจังหวะหลังจากการหน่วงเวลา 3 วินาทีลอง {thread.sleep (3000); } catch (interruptedException e) {e.printStackTrace (); } thread1.interrupt (); printContent ("การขัดจังหวะการดำเนินการ"); } ชั้นเรียนแบบคงที่แบบสแตติก 1 ขยายเธรด {@Override โมฆะสาธารณะเรียกใช้ () {RESETTIME (); int num = 0; ในขณะที่ (จริง) {ถ้า (isInterrupted ()) {printContent ("เธรดปัจจุบัน isInterrupted"); หยุดพัก; } num ++; if (num % 100 == 0) {printContent ("num:" + num); -รหัสด้านบนคือการเริ่มต้นเธรด Thread1 และเพิ่ม 1 ถึง NUM อย่างต่อเนื่องในขณะที่ลูปของเธรด Thread1 และพิมพ์ทุกครั้งที่หลาย 100 (ป้องกันการพิมพ์จากเร็วเกินไป) จากนั้นหลังจากนอนหลับเป็นเวลา 3000 มิลลิวินาทีเธรดหลักจะเรียกวิธีการขัดจังหวะของเธรด Thread1 แล้วมาดูเอาต์พุต:
ขัดจังหวะ
จะเห็นได้ว่าหลังจากใช้เวลาประมาณ 3,000 มิลลิวินาทีนั่นคือหลังจากที่ด้ายหลักจะนอนหลับด้าย 1 หยุดและเธรดด้ายจะหยุดลงเนื่องจากวิธีการที่ถูกขัดจังหวะในขณะที่ลูปกลับมาจริง กล่าวคือบทบาทของการขัดจังหวะและการขัดจังหวะที่นี่เทียบเท่ากับบทบาทของ setxx และ getxx รักษาตัวแปรบูลีน
การจัดการข้อยกเว้นขัดจังหวะ
แน่นอนว่ากลไกการขัดจังหวะไม่ได้เป็นเพียงการเปลี่ยนแปลงและการตรวจจับบิตสถานะอินเตอร์รัปต์ แต่ยังสามารถจัดการกับข้อยกเว้นขัดจังหวะได้ เรารู้ว่าเมธอด thread.sleep () จำเป็นต้องจับข้อยกเว้นขัดจังหวะดังนั้นขอเพิ่มความล่าช้าในการนอนหลับและลองใช้
ในขณะที่ (จริง) {ถ้า (isInterrupted ()) {printContent ("เธรดปัจจุบัน isInterrupted"); หยุดพัก; } num ++; // นอนลอง {thread.sleep (1); } catch (interruptedException e) {e.printStackTrace (); } if (num % 100 == 0) {printContent ("num:" + num); -มาดูผลลัพธ์ผลลัพธ์:
ขัดจังหวะ
ที่นี่เราจะพบว่าหลังจากนอนหลับค่า NUM เอาท์พุทมีขนาดเล็กลงอย่างมีนัยสำคัญ (NUMs ถึง 1 พันล้านเมื่อพวกเขาไม่ได้นอนหลับและดูเหมือนว่า CPU จะดำเนินการง่าย ๆ อย่างรวดเร็ว) ฮ่าฮ่า แต่นี่ไม่ใช่ประเด็น ประเด็นก็คือหลังจากข้อยกเว้นเอาต์พุตเอาต์พุต isinterrupted ส่งกลับเท็จและเธรดเธรด 1 ยังคงดำเนินการต่อไปและไม่ออกจากการวนซ้ำในขณะที่ แล้วทำไมถึงเป็นเช่นนี้? เราเพิ่งเพิ่มการนอนหลับ
หากมีการดำเนินการในเธรด Thread1 ที่จำเป็นต้องจับข้อยกเว้น InterruptedException เช่นการนอนหลับของเธรดการเข้าร่วมวิธีการรอของวัตถุการรอของเงื่อนไข ฯลฯ มันบังคับให้ข้อยกเว้น interruptedException จับเมื่อวิธีการเธรด 1 จากนั้นในขณะที่ลูปข้อยกเว้นนี้สามารถถูกจับได้และหลังจากนั้นก็ถูกโยนข้อยกเว้นนี้ธงขัดจังหวะเธรดจะถูกรีเซ็ตเป็นเท็จทันที ดังนั้นเมื่อมันถูกขัดจังหวะในครั้งต่อไปในขณะที่ลูปถูกกำหนดให้เป็นเท็จมันจะไม่แตกและจากนั้นในขณะที่ลูปจะดำเนินการต่อไป
ดังนั้นวิธีการขัดจังหวะ () จะดำเนินการที่แตกต่างกันโดยขึ้นอยู่กับว่ามีรหัสในวิธีการเรียกใช้ในเธรดเธรดที่ต้องจับ InterruptedException:
สถานการณ์แอปพลิเคชันของการขัดจังหวะ
โดยปกติแล้วการขัดจังหวะจะเหมาะสำหรับการตัดสินของลูปมาร์คในการดำเนินการเธรดเช่น
ในขณะที่ (! isInterrupted ()) {... } อย่างไรก็ตามหากมีการอุดตันในลูปนี้เธรดไม่สามารถตัดสินแท็กที่ไม่ผ่านการต่อไปได้และแม้ว่าวิธีการขัดจังหวะ () จะเรียกว่ามันไม่สามารถออกจากลูปและเธรดไม่สามารถออกได้ ตัวอย่างเช่น
ในขณะที่ (! isInterrupted ()) {... ในขณะที่ (จริง) {// เธรดติดอยู่ที่นี่กลไกที่ถูกขัดจังหวะไม่สามารถตอบสนองต่อ}} ได้ด้วยวิธีนี้การขัดจังหวะจะหมดหนทางและเธรดจะดำเนินการต่อไปและจะไม่ถูกขัดจังหวะและหยุด
ทดสอบตัวอย่างเพื่อดู github ของฉัน-javatest
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น