1. คิวการบล็อกคืออะไร?
คิวเป็นโครงสร้างข้อมูลที่มีการดำเนินการพื้นฐานสองประการ: การเพิ่มองค์ประกอบในตอนท้ายของคิวและลบองค์ประกอบออกจากหัวของคิว ความแตกต่างระหว่างทีมปิดกั้นและคิวทั่วไปคือคิวธรรมดาจะไม่บล็อกเธรดปัจจุบัน เมื่อต้องเผชิญกับแบบจำลองผู้ผลิตผู้บริโภคที่คล้ายคลึงกันต้องใช้กลยุทธ์การซิงโครไนซ์เพิ่มเติมและกลยุทธ์การปลุกแบบอินเตอร์เธรด การใช้คิวการบล็อกจะบล็อกเธรดปัจจุบัน เมื่อคิวว่างเปล่าการดำเนินการที่ได้รับองค์ประกอบจากคิวจะถูกบล็อก เมื่อคิวเต็มการดำเนินการของการเพิ่มองค์ประกอบในคิวก็จะถูกบล็อก
2. คิวการบล็อกหลักและวิธีการของมัน
แพ็คเกจ java.util.concurrent มีคิวการบล็อกหลักหลายอย่างส่วนใหญ่ดังนี้:
1) ArrayBlockingQueue: คิวการบล็อกตามการใช้งานอาร์เรย์ เมื่อสร้างวัตถุ ArrayblockingQueue ต้องระบุความจุ นอกจากนี้ยังสามารถระบุสำหรับนโยบายการเข้าถึง โดยค่าเริ่มต้นมันไม่ยุติธรรมนั่นคือไม่รับประกันว่าเธรดที่มีเวลารอคอยที่ยาวที่สุดจะสามารถเข้าถึงคิวก่อนได้
2) LinkedBlockingQueue: คิวการบล็อกตามรายการที่เชื่อมโยง หากไม่ได้ระบุขนาดความจุเมื่อสร้างวัตถุ LinkedBlockingQueue ขนาดเริ่มต้นคือจำนวนเต็ม max_value
3) คิวสองคิวข้างต้นเป็นคิวครั้งแรกในครั้งแรก แต่ PriorityBlockingQueue ไม่ได้ มันจะเรียงลำดับองค์ประกอบตามลำดับความสำคัญขององค์ประกอบและ dequeue ตามลำดับความสำคัญ แต่ละองค์ประกอบ dequeue เป็นองค์ประกอบลำดับความสำคัญสูงสุด โปรดทราบว่าคิวการบล็อกนี้เป็นคิวการปิดกั้นที่ไม่มีขอบเขตนั่นคือไม่มีขีด จำกัด สูงสุดเกี่ยวกับความจุ (คุณสามารถรู้ได้ผ่านซอร์สโค้ดที่ไม่มีการตั้งค่าสถานะสัญญาณที่เต็มไปด้วยคอนเทนเนอร์) สองประเภทแรกคือคิวที่มีขอบเขต
4) DelayQueue: ขึ้นอยู่กับ PriorityQueue, คิวการปิดกั้นหน่วงเวลา องค์ประกอบใน delayqueue สามารถรับองค์ประกอบจากคิวเมื่อถึงเวลาหน่วงเวลาที่ระบุ DelayQueue ยังเป็นคิวที่ไม่มีขอบเขตดังนั้นการดำเนินการ (ผู้ผลิต) ของการแทรกข้อมูลลงในคิวจะไม่ถูกบล็อกและเฉพาะการดำเนินการ (ผู้บริโภค) ของการรับข้อมูลเท่านั้นที่จะถูกบล็อก
การปิดกั้นคิวรวมถึงวิธีการส่วนใหญ่ในคิวที่ไม่ปิดกั้นและให้วิธีการอื่น ๆ ที่มีประโยชน์อื่น ๆ อีกมากมาย:
วิธีการวางจะใช้ในการจัดเก็บองค์ประกอบไว้ที่หางของคิวและหากคิวเต็มรอ
ใช้วิธีการใช้เพื่อรับองค์ประกอบจากคิวและหากคิวว่างเปล่ารอ
วิธีการเสนอใช้เพื่อจัดเก็บองค์ประกอบที่หางของคิว หากคิวเต็มมันจะรอสักครู่ เมื่อถึงช่วงเวลาหากการแทรกไม่ประสบความสำเร็จมันจะกลับมาเป็นเท็จ มิฉะนั้นมันจะกลับมาเป็นจริง
วิธีการสำรวจความคิดเห็นใช้เพื่อรับองค์ประกอบจากคิวแรก หากคิวว่างเปล่ามันจะรอสักครู่ เมื่อถึงช่วงเวลาหากได้รับการเรียกคืนมันจะกลับมาเป็นโมฆะ มิฉะนั้นจะส่งคืนองค์ประกอบที่ได้รับ;
นี่คือรหัส:
นำเข้า java.util.concurrent.arrayblockingqueue;/** * @author ผู้แต่ง: xu jiane-mail: [email protected] * @version สร้างขึ้น: 20 มีนาคม 2016 เวลา 12:52:53 PM * คำอธิบายชั้นเรียน */คลาสสาธารณะ java.util.concurrent.blockingqueue <string> blockingqueue = new ArrayBlockingQueue <> (5); สำหรับ (int i = 0; i <10; i ++) {// เพิ่มองค์ประกอบที่ระบุลงในคิวนี้ blockingqueue.put ("เพิ่มองค์ประกอบ"+i); System.out.println ("เพิ่มองค์ประกอบลงในคิวการบล็อก:" + i); } system.out.println ("โปรแกรมสิ้นสุดในเวลานี้และจะออก ----"); -
เมื่อจำนวนคิวการปิดกั้นขีด จำกัด คือ 5 หลังจากเพิ่ม 5 องค์ประกอบกระบวนการจะถูกบล็อกนอกคิวและรอและโปรแกรมจะไม่สิ้นสุดในเวลานี้
เมื่อคิวเต็มเราจะลบองค์ประกอบส่วนหัวออกและเราสามารถเพิ่มองค์ประกอบในคิวการบล็อกต่อไป รหัสมีดังนี้:
การปิดกั้นคลาสสาธารณะ {โมฆะคงที่สาธารณะหลัก (สตริง [] args) พ่น InterruptedException {java.util.concurrent.blockingqueue <String> blockingqueue = new ArrayBlockingQueue <> (5); สำหรับ (int i = 0; i <10; i ++) {// เพิ่มองค์ประกอบที่ระบุลงในคิวนี้ blockingqueue.put ("เพิ่มองค์ประกอบ"+i); System.out.println ("เพิ่มองค์ประกอบลงในคิวการบล็อก:" + i); if (i> = 4) system.out.println ("ลบองค์ประกอบส่วนหัว" +blockingqueue.take ()); } system.out.println ("โปรแกรมสิ้นสุดในเวลานี้และจะออก ----"); -ผลการดำเนินการมีดังนี้:
3. หลักการดำเนินการของการปิดกั้นคิว <br /> ต่อไปนี้ส่วนใหญ่ดูที่หลักการการดำเนินการของ Arrayblockingqueue
ก่อนอื่นมาดูตัวแปรสมาชิกของคลาส ArrayBlockingQueue:
คลาสสาธารณะ arrayblockingqueue <e> ขยาย Abstractqueue <e> ใช้การบล็อกการปิดกั้น <e>, java.io.serializable { / ** โครงสร้างการจัดเก็บข้อมูลการจัดเก็บพื้นฐาน* / รายการสุดท้าย [] รายการ; / ** ทีมงานส่วนหัวของหัวหน้า*/ int TakeIndex; / ** Team Tail Element Subscript*/ int Putindex; / ** จำนวนองค์ประกอบคิวทั้งหมด*/ int นับ; / ** reentrantlock*/ สุดท้าย reentrantlock ล็อค; / ** เงื่อนไขการรอคอย notempty*/ เงื่อนไขสุดท้ายส่วนตัว notempty; / ** เงื่อนไขการรอคอยที่น่าสนใจ*/ เงื่อนไขสุดท้ายส่วนตัว Notfull; /** * สถานะที่ใช้ร่วมกันสำหรับตัววนซ้ำที่ใช้งานอยู่ในปัจจุบันหรือเป็นโมฆะหากมี * เป็นที่รู้จักกันว่าจะไม่เป็น อนุญาตให้การดำเนินการคิวอัปเดตสถานะตัววนซ้ำ * */ transient itrs itrs = null;อย่างที่คุณเห็น arrayblockingqueue ที่ใช้ในการจัดเก็บองค์ประกอบเป็นอาร์เรย์
ลองมาดูการใช้วิธีการสำคัญสองวิธีของ ArrayblockingQueue, Put () และ Take ():
โมฆะสาธารณะใส่ (e e) พ่น InterruptedException {// ตรวจสอบก่อนว่า e เป็น checknotnull (e) ว่างเปล่า; // ได้รับการล็อคสุดท้าย reentrantlock lock = this.lock; lock.lockinctibly (); ลอง {// เมื่อคิวเต็มให้ป้อนเงื่อนไขและรอในขณะที่ (count == items.length) notfull.await (); // คิวไม่พอใจดำเนินการคิวการดำเนินการ enqueue (E); } ในที่สุด {// ปล่อยล็อคล็อค. unlock (); - มาดูการดำเนินการเข้าร่วมเฉพาะ:
โมฆะส่วนตัว enqueue (e x) {วัตถุสุดท้าย [] รายการ = this.items; // รายการการเอนเอียง [Putindex] = x; if (++ putindex == items.length) putindex = 0; // จำนวนคิวทั้งหมด +1 นับ ++; // เลือกเธรดแบบสุ่มในชุดรอของเงื่อนไข notempty เพื่อปลดบล็อกสถานะการปิดกั้น notempty.signal (); - นี่คือซอร์สโค้ดของวิธีการ ():
สาธารณะ E TAPE () พ่น InterruptedException {// ได้รับการล็อคครั้งสุดท้าย reentrantlock lock = this.lock; lock.lockinctibly (); ลอง {// คิวว่างเปล่าในขณะที่ (count == 0) // เธรดเข้าร่วมเงื่อนไขการรอคอยที่ไม่ได้ตั้งค่า notempty.await (); // ไม่ว่างเปล่าออกจากคิว return dequeue (); } ในที่สุด {// ปล่อยล็อคล็อค. unlock (); - 4. แอปพลิเคชันของการปิดกั้นคิว: การใช้โมเดลผู้ผลิตผู้ผลิต
/** * @author Author: Xu Jiane-Mail: [email protected] * @Version เวลาที่สร้างขึ้น: 20 มีนาคม 2016 เวลา 2:21:55 น. * คำอธิบายชั้นเรียน: โหมดผู้ผลิตผู้ผลิตโดยการปิดกั้นคิว */ชั้นเรียนสาธารณะ arrayblockingqueue ส่วนตัว <integer> queue = new ArrayBlockingQueue <จำนวนเต็ม> (คิว); โมฆะคงที่สาธารณะหลัก (สตริง [] args) {ทดสอบทดสอบ = การทดสอบใหม่ (); ผู้ผลิตผู้ผลิต = ทดสอบใหม่ผู้ผลิต (); ผู้บริโภคผู้บริโภค = ทดสอบใหม่ผู้บริโภค (); producer.start (); consumer.start (); } ผู้บริโภคในชั้นเรียนขยายเธรด {@Override โมฆะสาธารณะเรียกใช้ () {การบริโภค (); } การบริโภคโมฆะส่วนตัว () {ในขณะที่ (จริง) {ลอง {queue.take (); System.out.println ("ใช้องค์ประกอบจากคิวและคิวยังคงอยู่" + queue.size () + "องค์ประกอบ"); } catch (interruptedException e) {e.printStackTrace (); }}}} ผู้ผลิตคลาสขยายเธรด {@Override โมฆะสาธารณะเรียกใช้ () {produce (); } โมฆะส่วนตัวผลิต () {ในขณะที่ (จริง) {ลอง {queue.put (1); System.out.println ("แทรกองค์ประกอบลงในคิวพื้นที่ที่เหลือในคิว:"+ (คิว - คิว - queue.size ())); } catch (interruptedException e) {e.printStackTrace (); -
ข้างต้นเป็นเรื่องเกี่ยวกับบทความนี้ฉันหวังว่ามันจะเป็นประโยชน์กับการเรียนรู้ของทุกคน