ฉากรอการแจ้งเตือน
ฉากรอการรอคอยทั่วไปโดยทั่วไปเกี่ยวข้องกับเนื้อหาสองรายการต่อไปนี้:
1. ตัวแปรสถานะ
เมื่อเธรดต้องการรอมันมักเกิดจากเงื่อนไขบางอย่าง ตัวอย่างเช่นการเติมคิวเมื่อองค์ประกอบคิวเต็มเธรดจะต้องหยุดทำงาน เมื่อองค์ประกอบของคิวว่างให้ดำเนินการต่อไป
2. เงื่อนไข
เมื่อเธรดถูกกำหนดว่าจะเข้าสู่การรอคอยหรือตื่นขึ้นจากการแจ้งเตือนคุณจำเป็นต้องทดสอบว่ามีการปฏิบัติตามเงื่อนไขสถานะหรือไม่ ตัวอย่างเช่นการเพิ่มองค์ประกอบลงในคิวคิวเต็มดังนั้นจึงบล็อกเธรดปัจจุบัน ด้าย." ในเวลานี้กระบวนการรอองค์ประกอบจะถูกปลุกขึ้นมาแล้วตัดสินว่ามีที่ว่างสำหรับคิวในปัจจุบันจริง ๆ หรือไม่ Next Wake -Up
3. คิวเงื่อนไข
แต่ละวัตถุมีคิวเงื่อนไขในตัว
สังเกต
รอและแจ้งเป็นส่วนสำคัญของกลไกการซิงโครไนซ์ Java เมื่อรวมกับการใช้คำหลักที่ซิงโครไนซ์สามารถสร้างโมเดลซิงโครนัสที่ยอดเยี่ยมมากมายเช่นโมเดลผู้ผลิตผู้ผลิต แต่เมื่อใช้ฟังก์ชั่น (), แจ้ง (), ฟังก์ชั่นแจ้งเตือน () คุณต้องให้ความสนใจเป็นพิเศษกับประเด็นต่อไปนี้:
wait (), notify (), notifyall () วิธีการไม่ได้อยู่ในคลาสเธรด แต่เป็นของคลาสรากฐานวัตถุนั่นคือแต่ละวัตถุมีฟังก์ชั่นของการรอ (), แจ้ง () และแจ้ง () เนื่องจากแต่ละวัตถุถูกล็อคล็อคจึงเป็นพื้นฐานของแต่ละวัตถุดังนั้นวิธีการล็อคการทำงานจึงเป็นพื้นฐานที่สุด
โทรหาวิธีการรอของ OBJ () และแจ้งเตือน () คุณต้องได้รับการล็อค OBJ นั่นคือคุณต้องเขียนในส่วนที่ซิงโครไนซ์ (OBJ) {... } เซ็กเมนต์รหัส
หลังจากเรียก obj.wait () เธรด A จะปล่อยล็อคของ OBJ มิฉะนั้นเธรด B ไม่สามารถรับ OBJ Lock ได้และมันจะไม่สามารถปลุกเธรด A ในรหัสที่ซิงโครไนซ์ (OBJ) {... } เซ็กเมนต์
เมื่อเมธอด obj.wait () ส่งคืนเธรด A จำเป็นต้องได้รับการล็อค OBJ อีกครั้งเพื่อดำเนินการต่อ
หากเธรด A1, A2, A3 อยู่ใน obj.wait () เธรด B เรียก obj.notify () สามารถปลุกหนึ่งในเธรด A1, A2, A3 (ซึ่งถูกกำหนดโดย JVM)
หากเธรด B เรียก obj.notifyall () เขาทุกคนสามารถตื่นขึ้นมาพร้อมกับเธรดรอ A1, A2, A3 แต่เธรดที่รอคอยเพื่อดำเนินการต่อประโยคต่อไปของ OBJ.Wait () คุณต้องได้รับการล็อค OBJ ดังนั้นเธรด A1, A2, A3 มีโอกาสเพียงครั้งเดียวที่จะได้รับการล็อคและดำเนินการต่อไป
เมื่อเธรด B เรียกว่า obj.notify () หรือ obj.notifyall () เธรด B กำลังถือ OBJ Lock จนกว่าเธรด B จะออกจากบล็อกรหัสที่ซิงโครไนซ์และปล่อย OBJ Lock หนึ่งในเธรด A1, A2, A3 มีโอกาสได้ล็อควัตถุและดำเนินการต่อไป
ตัวอย่างเช่นรหัส
โครงสร้างรหัสทั่วไปของการทำงานรอของเธรดมีดังนี้:
การทดสอบโมฆะสาธารณะ () พ่น InterruptedException {ซิงโครไนซ์ (obj) {ในขณะที่ (! contidition) {obj.wait ();}}}}}}}}}}
เหตุใดการดำเนินงาน OBJ.Wait () จึงต้องอยู่ในวงจร? มีเหตุผลหลักหลายประการ:
1. การล็อควัตถุอาจใช้เพื่อปกป้องตัวแปรหลายสถานะ ตัวอย่างเช่นวัตถุบางอย่างล็อค OBJ เพื่อปกป้องตัวแปรสถานะทั้งสอง A และ B เมื่อไม่ได้รับการยืนยันเงื่อนไขการดำเนินการรอคอย ตอนนี้หากการดำเนินการของตัวแปรสถานะเกิดขึ้นการดำเนินการแจ้งเตือนจะเรียกว่า OBJ แล้วเธรดทั้งหมดในคิวเงื่อนไขที่สอดคล้องกับ OBJ จะถูกปลุกขึ้นมา สำหรับ B ยังถูกปลุกให้ตื่นขึ้นในเวลานี้ดังนั้นคุณต้องรีไซเคิลว่าเงื่อนไขของ B จะพบได้หรือไม่
2. เงื่อนไขของสถานะเดียวกันของหลายเธรดได้รับการยืนยัน ตัวอย่างเช่นฉากของการเพิ่มองค์ประกอบในคิวคิวปัจจุบันเต็มและหลายเธรดต้องการเพิ่มองค์ประกอบภายในดังนั้นจึงเป็นทั้งหมด ในเวลานี้เธรดอื่นนำองค์ประกอบออกมาจากคิวและเรียกว่าการดำเนินการแจ้งเตือนเพื่อปลุกเธรดทั้งหมด แต่มีเพียงเธรดเดียวเท่านั้นที่สามารถเพิ่มองค์ประกอบลงในคิวได้
3. การปลุกเท็จ โดยไม่ต้องได้รับการแจ้งเตือนให้ขัดจังหวะการเปิดตัวเธรดจะถูกปลุกโดยอัตโนมัติ แม้ว่าสถานการณ์นี้จะไม่ค่อยเกิดขึ้นในทางปฏิบัติ แต่สถานการณ์นี้สามารถกำจัดได้ผ่านการรอรอบ