ฟังก์ชั่นของเงื่อนไขคือการควบคุมการล็อคที่แม่นยำยิ่งขึ้น วิธีการรอคอย () ในสภาพเท่ากับวิธีการรอ () ของวัตถุวิธีการสัญญาณ () ในสภาพมีค่าเทียบเท่ากับวิธีการแจ้งเตือน () ของวัตถุและ signalall () ในสภาพเทียบเท่ากับวิธีการแจ้งเตือน () ของวัตถุ ความแตกต่างคือวิธีการรอ (), แจ้งเตือน () และ notifyall () ในวัตถุนั้นรวมกับ "การล็อคแบบซิงโครไนซ์" (คำหลักที่ซิงโครไนซ์); และเงื่อนไขจะต้องรวมกับ "mutex"/"Share Lock"
รายการฟังก์ชันเงื่อนไข
// ทำให้เธรดปัจจุบันรอจนกว่าจะได้รับสัญญาณหรือถูกขัดจังหวะ Void Await () // ทำให้เธรดปัจจุบันยังคงอยู่ในสถานะรอก่อนที่จะได้รับสัญญาณถูกขัดจังหวะหรือถึงเวลารอที่ระบุ บูลีนรอคอย (เป็นเวลานานหน่วย TimeUnit) // ทำให้เธรดปัจจุบันอยู่ในสถานะรอจนกว่าจะได้รับสัญญาณถูกขัดจังหวะหรือถึงเวลารอที่ระบุ Long Awaitnanos (Long Nanostimeout) // ทำให้เธรดปัจจุบันอยู่ในสถานะรอก่อนที่จะได้รับสัญญาณ Void Awaituninterinctibly () // ทำให้เธรดปัจจุบันยังคงอยู่ในสถานะรอจนกว่าจะได้รับสัญญาณถูกขัดจังหวะหรือถึงกำหนดเวลาที่ระบุ Boolean Awaituntil (กำหนดเวลาวันที่) // ปลุกเธรดรอ เป็นโมฆะสัญญาณ () // ปลุกเธรดที่รอทั้งหมด เป็นโมฆะ SignalAll ()
ตัวอย่างการใช้งานคลาส
เงื่อนไขจะแบ่งวิธีการตรวจสอบวัตถุ (รอแจ้งและแจ้งเตือน) ลงในวัตถุที่แตกต่างกันอย่างสิ้นเชิงเพื่อให้การรวมวัตถุเหล่านี้เข้ากับการใช้งานล็อคใด ๆ แต่ละวัตถุจะมีชุดรอหลายชุด ในหมู่พวกเขาล็อคแทนที่การใช้วิธีการที่ซิงโครไนซ์และคำสั่งและเงื่อนไขแทนที่การใช้วิธีการตรวจสอบวัตถุ ต่อไปนี้เป็นตัวอย่างที่เป็นลายลักษณ์อักษรก่อนหน้านี้ของการสื่อสารเธรดที่มีการใช้งานที่มีเงื่อนไขรหัสมีดังนี้:
ชั้นเรียนสาธารณะ ThreadTest2 {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {ธุรกิจธุรกิจขั้นสุดท้าย = ธุรกิจใหม่ (); เธรดใหม่ (ใหม่ runnable () {@Override โมฆะสาธารณะ run () {threadexecute (ธุรกิจ, "sub");}}). start (); theadexecute (ธุรกิจ "หลัก"); } โมฆะสาธารณะคงที่ threadexecute (ธุรกิจธุรกิจ, สตริง theadType) {สำหรับ (int i = 0; i <100; i ++) {ลอง {ถ้า ("main" .equals (thestType)) {Business.main (i); } else {business.sub (i); }} catch (interruptedException e) {e.printStackTrace (); }}}} คลาสธุรกิจ {บูลีนบูลีนส่วนตัว = true; ล็อคส่วนตัว = ใหม่ reentrantlock (); เงื่อนไขส่วนตัว = lock.newCondition (); สาธารณะ /*ซิงโครไนซ์* / void main (int loop) พ่น InterruptedException {lock.lock (); ลอง {ในขณะที่ (bool) {edition.await (); // this.wait (); } สำหรับ (int i = 0; i <100; i ++) {system.out.println ("เธรดหลัก seq ของ" + i + ", ลูปของ" + ลูป); } bool = true; เงื่อนไข. signal (); // this.notify (); } ในที่สุด {lock.unlock (); }} สาธารณะ /*ซิงโครไนซ์* / void sub (int loop) พ่น InterruptedException {lock.lock (); ลอง {ในขณะที่ (! bool) {edition.await (); // this.wait (); } สำหรับ (int i = 0; i <10; i ++) {system.out.println ("เธรดย่อย seq ของ" + i + ", ลูปของ" + ลูป); } bool = false; เงื่อนไข. signal (); // this.notify (); } ในที่สุด {lock.unlock (); - ในสภาพให้แทนที่การรอ () ด้วยการรอ () แทนที่การแจ้งเตือน () ด้วยสัญญาณ () และแทนที่ NotifyAll () ด้วย SignalAll () วิธีการสื่อสารแบบดั้งเดิมของเธรดสามารถนำไปใช้ได้ หมายเหตุที่นี่เงื่อนไขนั้นถูกผูกไว้กับการล็อค ในการสร้างล็อคคุณต้องใช้วิธีการใหม่ ()
ด้วยวิธีนี้เงื่อนไขไม่แตกต่างจากการสื่อสารเธรดแบบดั้งเดิม พลังของเงื่อนไขคือมันสามารถสร้างเงื่อนไขที่แตกต่างกันระหว่างหลายเธรด ต่อไปนี้เป็นส่วนหนึ่งของรหัสจาก API เพื่อแสดง
คลาส BoundedBuffer {ล็อคสุดท้ายล็อค = ใหม่ reentrantlock (); // ล็อควัตถุเงื่อนไขสุดท้ายเงื่อนไข notfull = lock.newcondition (); // เขียนเงื่อนไขด้ายเงื่อนไขสุดท้ายเงื่อนไข notempty = lock.newCondition (); // อ่านเงื่อนไขของด้าย*/countptr inducted คิว*/; โมฆะสาธารณะใส่ (วัตถุ x) พ่น InterruptedException {lock.lock (); ลอง {ในขณะที่ (count == items.length) // ถ้าคิวเต็มไปด้วย notfull.await (); // บล็อกรายการด้ายเขียน [putptr] = x; // กำหนดถ้า (++ putptr == items.length) putptr = 0; เธรด} ในที่สุด {lock.unlock (); }} วัตถุสาธารณะใช้ () พ่น InterruptedException {lock.lock (); ลอง {ในขณะที่ (count == 0) // ถ้าคิวว่างเปล่า notempty.await (); // บล็อกวัตถุกระทู้อ่าน x = รายการ [takeptr]; // เลือกค่าถ้า (++ takeptr == items.length) takeptr = 0; } ในที่สุด {lock.unlock (); - นี่คือพื้นที่แคชในสภาพแวดล้อมการทำงานแบบมัลติเธรด พื้นที่แคชมีสองวิธี: ใส่และใช้ ใส่คือการจัดเก็บข้อมูลใช้คือการดึงข้อมูลและมีคิวแคชอยู่ข้างใน ดูรหัสสำหรับตัวแปรเฉพาะและคำอธิบาย ฟังก์ชั่นที่ใช้โดยคลาสแคชพื้นที่นี้: หลายเธรดเก็บข้อมูลและดึงข้อมูลจากมัน ค่าแคชสูงสุดที่คิวแคช (ครั้งแรกในก่อนออกจากนั้นออกจากนั้นออกไป) สามารถแคชได้คือ 100 เธรดหลายเธรดเป็นเอกสิทธิ์เฉพาะบุคคลร่วมกัน เมื่อค่าที่เก็บไว้ในคิวแคชถึง 100 เธรดการเขียนจะถูกบล็อกและเธรดการอ่านจะถูกปลุก เมื่อค่าที่เก็บไว้ในคิวแคชคือ 0 เธรดการอ่านจะถูกบล็อกและเธรดการเขียนจะถูกปลุก การวิเคราะห์กระบวนการดำเนินการรหัสดังต่อไปนี้:
1. เธรดการเขียนดำเนินการและเรียกใช้วิธีการ
2. เพื่อตรวจสอบว่าการนับเป็น 100 เห็นได้ชัดว่าไม่มี 100;
3. ดำเนินการต่อเพื่อดำเนินการและฝากค่า;
4. หลังจากพิจารณาตำแหน่งดัชนีที่เป็นลายลักษณ์อักษรในปัจจุบัน ++ ไม่ว่าจะเท่ากับ 100. ทำให้ค่าดัชนีการเขียนเท่ากันเป็น 0 และนับ+1;
5. ตื่นขึ้นมาเพียงหนึ่งในการอ่านคิวการปิดกั้นเธรด;
6. ดำเนินการอ่านเธรดและเรียกใช้วิธีการ
7. …
8. ตื่นขึ้นมาเพียงหนึ่งในคิวบล็อกการเขียน
นี่คือพลังของหลายเงื่อนไข สมมติว่าคิวแคชนั้นเต็มแล้วการปิดกั้นเป็นเธรดการเขียนอย่างแน่นอนและการปลุกเป็นเธรดการอ่านอย่างแน่นอน ในทางตรงกันข้ามการปิดกั้นเป็นเธรดอ่านอย่างแน่นอนและการปลุกเป็นเธรดการเขียนอย่างแน่นอน แล้วจะเกิดอะไรขึ้นถ้ามีเพียงเงื่อนไขเดียว? คิวแคชเต็มรูปแบบล็อคนี้ไม่ทราบว่าเป็นเธรดอ่านหรือเธรดการเขียน หากการปลุกเป็นเธรดการอ่านทุกคนมีความสุข หากการปลุกเป็นเธรดการเขียนแล้วเธรดก็เพิ่งถูกปลุกและถูกบล็อกอีกครั้งแล้วตื่นขึ้นมาอีกครั้งซึ่งเสียเวลามาก