ฉันมักจะเรียกดู เกี่ยวกับการแจ้งเตือนและแจ้งเตือนใน Java ผู้คนมักจะมีข้อความดังต่อไปนี้:
การแจ้งเตือนจะแจ้งให้ทราบถึงการรอวัตถุเท่านั้นในขณะที่แจ้งเตือนจะแจ้งให้ทราบถึงการรอวัตถุทั้งหมดและวัตถุทั้งหมดจะดำเนินการต่อไป
และดูเหมือนว่ามีตัวอย่างที่จะพิสูจน์ คำสั่งข้างต้นสามารถกล่าวได้ว่าถูกต้องหรือไม่ เหตุผลก็คือหนึ่งในนั้นสำคัญมาก แถลงการณ์อย่างเป็นทางการมีดังนี้:
รอแจ้งแจ้งแจ้ง:
วิธีนี้ควรเรียกโดยเธรดที่เป็นเจ้าของของการตรวจสอบวัตถุนี้ เธรดสามารถเป็นเจ้าของจอภาพวัตถุนี้ได้ในหนึ่งในสามวิธี:
โดยการดำเนินการวิธีการอินสแตนซ์แบบซิงโครนัสของวัตถุนี้
เนื้อหาของคำสั่งที่ซิงโครไนซ์ดำเนินการโดยดำเนินการคำสั่งที่ซิงโครไนซ์ในวัตถุนี้
สำหรับวัตถุประเภทคลาสคุณสามารถดำเนินการวิธีการแบบซิงโครนัสแบบซิงโครนัสของคลาส
มีเธรดเพียงหนึ่งเดียวที่มีการตรวจสอบวัตถุในแต่ละครั้ง
ข้อความข้างต้นถูกตัดตอนมาจาก Javadoc ซึ่งหมายความว่าในการโทรจะต้องมีการตรวจสอบวัตถุ (เช่นล็อค) ซึ่งเราสามารถเข้าใจได้ว่าการทำงานภายในวิธีการซิงโครไนซ์ จากนั้นความหมายโดยนัยของคำสั่งนี้คือหากคุณต้องการดำเนินการบล็อกรหัสที่มีอยู่ในบล็อกการซิงโครไนซ์คุณจะต้องได้รับการล็อคอีกครั้ง ประโยคนี้อธิบายไว้ใน Javadoc:
รอ
วิธีนี้ทำให้เธรดปัจจุบัน (เรียกว่า t) วางตัวเองในชุดรอของวัตถุจากนั้นละทิ้งข้อกำหนดการซิงโครไนซ์ทั้งหมดในวัตถุนี้ สำหรับวัตถุประสงค์ในการตั้งเวลาเธรดเธรด t ถูกปิดใช้งานและอยู่ในการจำศีลก่อนที่จะเกิดสถานการณ์หนึ่งในสี่สถานการณ์ต่อไปนี้:
เธรดอื่น ๆ บางอย่างเรียกวิธีการแจ้งเตือนของวัตถุนี้และเธรด t จะถูกเลือกเป็นทางเลือกเป็นเธรดปลุก
เธรดอื่น ๆ บางอย่างเรียกวิธีการแจ้งเตือนของวัตถุนี้
เธรดอื่น ๆ ขัดจังหวะเธรด T.
ประมาณเวลาจริงที่ระบุแล้ว อย่างไรก็ตามหากหมดเวลาเป็นศูนย์เวลาจริงจะไม่ถูกนำมาพิจารณาและเธรดจะรอจนกว่าจะได้รับการแจ้งเตือน
จากนั้นเธรด t จะถูกลบออกจากชุดรอของวัตถุและการกำหนดตารางเวลาเธรดจะดำเนินการอีกครั้ง เธรดจากนั้นแข่งขันกับเธรดอื่น ๆ ในวิธีทั่วไปเพื่อให้ได้สิทธิ์ในการซิงโครไนซ์บนวัตถุ; เมื่อได้รับการควบคุมวัตถุแล้วการประกาศการซิงโครไนซ์ทั้งหมดของวัตถุจะได้รับการกู้คืนสู่สถานะก่อนหน้าของพวกเขาซึ่งก็คือการรอการรอ
สถานการณ์เมื่อวิธีการคือ เธรด t จากนั้นส่งคืนจากการโทรไปยังวิธีการรอ ดังนั้นเมื่อกลับมาจากวิธีการรอสถานะการซิงโครไนซ์ของวัตถุและเธรด t จะเหมือนกับเมื่อเรียกใช้วิธีการรอ
นั่นคือการล็อคจะต้องได้รับการจัดเก็บใหม่เพื่อให้ได้รับแจ้งเธรดทั้งหมดได้รับการแจ้งเตือน อย่างไรก็ตามเธรดเหล่านี้จะแข่งขันและมีเพียงเธรดเดียวเท่านั้นที่จะได้รับการล็อคได้สำเร็จ ก่อนที่เธรดนี้จะถูกดำเนินการเธรดอื่น ๆ จะต้องรอ (แต่ไม่จำเป็นต้องแจ้งเตือนการแจ้งเตือนที่นี่เนื่องจากเป็นแจ้งเตือนและจำเป็นต้องได้รับการล็อคเท่านั้น) มีรหัสต่อไปนี้ที่สามารถทำซ้ำปรากฏการณ์นี้
ก่อนอื่นกำหนดคลาสเธรดที่สามารถเรียกใช้ดังนี้:
วัตถุสุดท้ายคงที่ส่วนตัว obj = วัตถุใหม่ (); คลาสคงที่ R ใช้งาน Runnable {int i; r (int i) {this.i = i; } โมฆะสาธารณะเรียกใช้ () {ลอง {ซิงโครไนซ์ (obj) {system.out.println ("เธรด->" + i + "รอ"); obj.wait (); System.out.println ("Thread->" + i + "Running"); Thread.sleep (30000); }} catch (exception e) {e.printstacktrace (); }}} ให้ความสนใจกับด้านในของวิธีการวิ่งด้านบน หลังจากรอ () เราพิมพ์ประโยคแล้วหยุดรหัสปัจจุบันชั่วคราวเป็นเวลา 30 วินาที เกี่ยวกับวิธีการนอนหลับมีการอธิบายดังนี้:
เธรดจะไม่สูญเสียความเป็นเจ้าของจอภาพใด ๆ
นั่นคือล็อคยังคงจัดขึ้น
จากนั้นกำหนดวิธีหลักในการเรียกใช้เธรดเหล่านี้ดังนี้:
เธรด [] rs = เธรดใหม่ [10]; สำหรับ (int i = 0; i <10; i ++) {rs [i] = เธรดใหม่ (ใหม่ r (i)); } สำหรับ (เธรด r: rs) {r.start (); } thread.sleep (5000); ซิงโครไนซ์ (obj) {obj.notifyall (); -เรากำหนด 10 เธรดแล้วเรียกใช้ทั้งหมด เนื่องจากมีรอ 10 เธรดจะรอหลังจากพิมพ์ "เริ่มวิ่ง" จากนั้นวิธีการหลักจะแจ้งเตือน ผลลัพธ์ที่นี่จะปรากฏดังนี้:
เธรด-> 0 กำลังรอเธรด-> 4 รอเธรด-> 5 รอเธรด-> 3 รอเธรด-> 2 รอเธรด-> 1 รอเธรด-> 6 รอเธรด-> 7 รอเธรด-> 8 รอเธรด-> 9 รอเธรด-> 9 กำลังทำงานอยู่
... ไม่มีผลลัพธ์อื่นภายใน 30 วินาที
ในเอาต์พุตข้างต้นหลังจากรอเพียงหนึ่งเธรดจะส่งออกคำสั่ง "กำลังทำงาน" และเป็นระยะเวลา (30 วินาทีที่นี่) จะไม่มีเอาต์พุตอื่น กล่าวคือเธรดอื่น ๆ จะไม่ส่งออกระหว่างล็อคที่ถือโดยรหัสปัจจุบัน
ข้อสรุปสุดท้ายคือ: หากเธรดรอต้องการรันต่อไปจะต้องเป็นไปตามเงื่อนไขสองประการ:
เธรดอื่น ๆ แจ้งเตือนหรือแจ้งเตือนได้รับแจ้งและเธรดปัจจุบันได้รับแจ้ง
หลังจากการแข่งขันกับเธรดอื่น ๆ เพื่อล็อคเงื่อนไขสองเงื่อนไขได้รับความสำเร็จสำหรับการล็อคและไม่มีทั้งสองหายไป ในความเป็นจริงในระดับการใช้งานแจ้งและแจ้งเตือนให้บรรลุผลเดียวกันและเธรดจะยังคงทำงานต่อไป แต่แจ้งเตือนได้รับการยกเว้น ความจำเป็นในการแจ้งเธรดอื่น ๆ หลังจากที่เธรดกำลังทำงานอยู่เพราะได้รับแจ้ง เมื่อใดควรใช้การแจ้งเตือนและเมื่อใดที่จะใช้ NotifyAll จะขึ้นอยู่กับสถานการณ์จริง
ข้างต้นเป็นการรวบรวมข้อมูลสำหรับการแจ้งเตือน Java และแจ้งเตือน เราจะยังคงเพิ่มข้อมูลที่เกี่ยวข้องในอนาคต ขอบคุณสำหรับการสนับสนุนเว็บไซต์นี้!