บล็อกคิวใน Java
1. คิวการบล็อกคืออะไร?
คิวการบล็อก (BlockingQueue) เป็นคิวที่รองรับการดำเนินการเพิ่มเติมสองครั้ง การดำเนินการเพิ่มเติมสองครั้งนี้คือ:
เมื่อคิวว่างเปล่าเธรดที่ดึงองค์ประกอบจะรอให้คิวไม่ว่างเปล่า
เมื่อคิวเต็มเธรดที่เก็บองค์ประกอบจะรอให้คิวพร้อมใช้งาน
การปิดกั้นคิวมักใช้ในสถานการณ์ของผู้ผลิตและผู้บริโภค ผู้ผลิตเป็นเธรดที่เพิ่มองค์ประกอบในคิวและผู้บริโภคเป็นเธรดที่ใช้องค์ประกอบจากคิว คิวการปิดกั้นคือภาชนะที่ผู้ผลิตเก็บองค์ประกอบและผู้บริโภคจะใช้องค์ประกอบจากภาชนะเท่านั้น
2. การปิดกั้นคิวใน Java
มีการปิดกั้นคิวเจ็ดคิวใน JDK:
arrayblockingqueue
ArrayblockingQueue เป็นคิวการปิดกั้นที่ถูกนำมาใช้โดยใช้อาร์เรย์ คิวนี้เรียงลำดับองค์ประกอบตามหลักการแรก (FIFO) ครั้งแรก (FIFO) โดยค่าเริ่มต้นผู้เข้าชมจะไม่รับประกันว่าจะเข้าถึงได้อย่างเป็นธรรม คิวที่สามารถเข้าถึงได้อย่างเป็นธรรมหมายถึงเธรดผู้ผลิตที่ถูกบล็อกทั้งหมดหรือเธรดผู้บริโภค เมื่อคิวพร้อมใช้งานคิวสามารถเข้าถึงได้ตามลำดับการบล็อก นั่นคือเธรดผู้ผลิตที่บล็อกก่อนสามารถแทรกองค์ประกอบลงในคิวก่อนและเธรดผู้บริโภคที่บล็อกก่อนสามารถรับองค์ประกอบจากคิวก่อน โดยปกติปริมาณงานจะลดลงเพื่อให้แน่ใจว่าเป็นธรรม เราสามารถสร้างคิวการบล็อกที่เป็นธรรมโดยใช้รหัสต่อไปนี้:
arrayblockingqueue fairqueue = ใหม่ arrayblockingqueue (1,000, จริง);
ความเป็นธรรมของการเข้าถึงนั้นทำได้ผ่านการล็อค Reentrantlock
linkedblockingqueue
LinkedBlockingQueue เป็นคิวการปิดกั้นที่มีขอบเขตนำมาใช้กับรายการที่เชื่อมโยง ความยาวเริ่มต้นและความยาวสูงสุดของคิวนี้คือจำนวนเต็ม max_value คิวนี้เรียงลำดับองค์ประกอบตามหลักการแรกในการออก
priorityblockingqueue
Priorityblockingqueue เป็นคิวที่ไม่มีขอบเขตซึ่งรองรับลำดับความสำคัญ โดยค่าเริ่มต้นองค์ประกอบจะถูกจัดเรียงตามลำดับตามธรรมชาติและกฎการสั่งซื้อขององค์ประกอบสามารถระบุได้ผ่านตัวเปรียบเทียบตัวเปรียบเทียบ องค์ประกอบจะถูกจัดเรียงตามลำดับจากน้อยไปมาก
การหน่วงเวลา
Delayqueue เป็นคิวการบล็อกที่ไม่มีขอบเขตซึ่งรองรับการได้มาซึ่งองค์ประกอบล่าช้า คิวถูกนำไปใช้โดยใช้ PriorityQueue องค์ประกอบในคิวจะต้องใช้อินเทอร์เฟซที่ล่าช้าและเมื่อสร้างองค์ประกอบคุณสามารถระบุระยะเวลาที่ใช้ในการรับองค์ประกอบปัจจุบันจากคิว องค์ประกอบสามารถสกัดได้จากคิวเมื่อความล่าช้าหมดอายุ เราสามารถใช้ delayqueue ในสถานการณ์แอปพลิเคชันต่อไปนี้:
การออกแบบระบบแคช: การหน่วงเวลาสามารถใช้เพื่อบันทึกระยะเวลาความถูกต้องขององค์ประกอบแคชและสามารถใช้เธรดเพื่อสืบค้นการหน่วงเวลา เมื่อองค์ประกอบสามารถรับได้จากการหน่วงเวลาหมายความว่าระยะเวลาของความถูกต้องของแคชมาถึงแล้ว
ตารางงานที่กำหนด ใช้ delayqueue เพื่อบันทึกงานและเวลาดำเนินการที่จะดำเนินการในวันนั้น เมื่องานได้รับจากการหน่วงเวลามันจะเริ่มดำเนินการ ตัวอย่างเช่นการจับเวลาจะถูกนำไปใช้โดยใช้ delayqueue
วิธีการใช้อินเทอร์เฟซล่าช้า
เราสามารถอ้างถึงคลาส ScheduledFutureTask ใน ScheduledThreadPoolexecutor คลาสนี้ใช้อินเทอร์เฟซที่ล่าช้า ขั้นแรก: เมื่อสร้างวัตถุให้ใช้เวลาในการบันทึกเมื่อสามารถใช้วัตถุก่อนการบันทึก รหัสมีดังนี้:
ScheduledFutureTask (Runnable R, V ผลลัพธ์, Long NS, ระยะยาว) {super (r, ผลลัพธ์); this.time = ns; this.period = ระยะเวลา; this.equencenumber = sequencer.getandincrement ();}จากนั้นใช้ getDelay เพื่อสอบถามระยะเวลาที่องค์ประกอบปัจจุบันต้องล่าช้า รหัสมีดังนี้:
GetDelay สาธารณะยาว (หน่วย TimeUnit) {return unit.Convert (เวลา - ตอนนี้ (), timeUnit.nanoseconds); -ผ่านตัวสร้างเราจะเห็นว่าหน่วยของพารามิเตอร์เวลาหน่วงเวลา NS คือนาโนวินาที เป็นการดีที่สุดที่จะใช้นาโนวินาทีเมื่อออกแบบด้วยตัวเองเพราะคุณสามารถระบุหน่วยใดก็ได้เมื่อได้รับ เมื่อใช้นาโนวินาทีเป็นหน่วยและเวลาหน่วงเวลาน้อยกว่านาโนวินาทีมันจะลำบาก เมื่อใช้โปรดทราบว่าเมื่อเวลาน้อยกว่าเวลาปัจจุบัน GetDelay จะส่งคืนจำนวนลบ
ในที่สุดเราสามารถใช้เวลาในการระบุคำสั่งซื้อในคิวตัวอย่างเช่น: ให้เวลาการหน่วงเวลาที่ยาวที่สุดถูกวางไว้ในตอนท้ายของคิว
public int compereto (ล่าช้าอื่น ๆ ) {ถ้า (อื่น ๆ == สิ่งนี้) ส่งคืน 0; if (อินสแตนซ์อื่น ๆ ของ scheduledFutureTask) {scheduledFutureTask x = (scheduledFutureTask) อื่น ๆ ; long diff = เวลา - x.time; ถ้า (diff <0) return -1; อื่นถ้า (diff> 0) return 1; อื่นถ้า (sequencenumber <x.equencenumber) return -1; อื่นกลับ 1; } long d = (getDelay (timeUnit.nanoseconds)-อื่น ๆ getDelay (timeUnit.nanoseconds)); return (d == 0)? 0: ((d <0)? -1: 1); -วิธีการใช้คิวการบล็อกล่าช้า
การใช้คิวการปิดกั้นการหน่วงเวลานั้นง่ายมาก เมื่อผู้บริโภคได้รับองค์ประกอบจากคิวหากองค์ประกอบไม่ถึงเวลาหน่วงจะบล็อกเธรดปัจจุบัน
ล่าช้ายาว = first.getDelay (timeutil.nanoseconds); if (ล่าช้า <= 0) {return q.poll; // การปิดกั้นคิว} อื่นถ้า (ผู้นำ! = null) {// ตะกั่วหมายถึงเธรดที่รอข้อความจากคิวการบล็อกที่มีอยู่ Await (); // ให้เธรดป้อนสัญญาณรอ} else {// เมื่อผู้นำเป็นโมฆะให้ตั้งเธรดปัจจุบันเป็น leaderThread thisThread = thread.currentThread (); ลอง {leader = thisthread; // ใช้วิธี AwaitNanos () -ซิงโครนัสคิว
Synchronousqueue เป็นคิวการปิดกั้นที่ไม่ได้เก็บองค์ประกอบ การดำเนินการแต่ละครั้งจะต้องรอการดำเนินการมิฉะนั้นไม่สามารถเพิ่มองค์ประกอบได้ Synchronousqueue ถือได้ว่าเป็นผู้สัญจรซึ่งรับผิดชอบในการส่งข้อมูลที่ประมวลผลโดยเธรดผู้ผลิตโดยตรงไปยังเธรดผู้บริโภค คิวเองไม่ได้เก็บองค์ประกอบใด ๆ ซึ่งเหมาะสำหรับสถานการณ์สกรรมกริยา ตัวอย่างเช่นข้อมูลที่ใช้ในเธรดหนึ่งจะถูกส่งไปยังเธรดอื่นเพื่อใช้งาน ปริมาณงานของ synchronousqueue สูงกว่าของ
LinkedBlockingQueue และ Arrayblockingqueue
รองรับคิวการเข้าถึงที่ยุติธรรม โดยค่าเริ่มต้นมันยังคงเป็นกลไกนโยบายที่ไม่เป็นธรรม
LinkedTransferqueue
LinkedTransferqueue เป็นคิวการถ่ายโอนที่ไม่มีขอบเขตซึ่งประกอบด้วยโครงสร้างรายการที่เชื่อมโยง เมื่อเปรียบเทียบกับคิวการปิดกั้นอื่น ๆ LinkedTransferqueue มีวิธีการ trytransfer และการถ่ายโอนมากขึ้น
วิธีการถ่ายโอน
หากผู้บริโภคกำลังรอที่จะได้รับองค์ประกอบ (เมื่อผู้บริโภคใช้วิธีการใช้ () หรือวิธีการสำรวจเวลา จำกัด ()) วิธีการถ่ายโอนสามารถถ่ายโอนองค์ประกอบที่ส่งผ่านโดยผู้ผลิตไปยังผู้บริโภคได้ทันที หากไม่มีผู้บริโภคกำลังรอองค์ประกอบที่ได้รับวิธีการถ่ายโอนจะเก็บองค์ประกอบไว้ในโหนดหางของคิวและรอจนกว่าผู้บริโภคจะใช้องค์ประกอบก่อนที่จะกลับมา
วิธี TryTransfer
มันถูกใช้เพื่อทดสอบว่าองค์ประกอบที่แนะนำโดยผู้ผลิตสามารถส่งโดยตรงไปยังผู้บริโภคได้หรือไม่ หากไม่มีผู้บริโภครอองค์ประกอบที่ได้รับเท็จจะถูกส่งคืน ความแตกต่างระหว่างวิธีการถ่ายโอนคือวิธีการ trytransfer จะกลับมาทันทีไม่ว่าผู้บริโภคจะได้รับหรือไม่ก็ตาม วิธีการถ่ายโอนจะต้องรอจนกว่าผู้บริโภคจะบริโภคก่อนที่จะกลับมา
สำหรับวิธีการ trytransfer (e, การหมดเวลายาว, หน่วย TimeUnit) ที่มีเวลา จำกัด มันพยายามที่จะผ่านองค์ประกอบที่ส่งผ่านโดยผู้ผลิตโดยตรงไปยังผู้บริโภค แต่ถ้าไม่มีผู้บริโภคบริโภคองค์ประกอบมันจะรอเวลาที่กำหนดก่อนกลับ หากการหมดเวลาไม่ได้ใช้องค์ประกอบมันจะกลับมาเป็นเท็จและหากองค์ประกอบถูกใช้ภายในเวลาหมดเวลามันจะกลับมาเป็นจริง
linkedblockingDeque
LinkedBlockingDeque เป็นคิวการบล็อกแบบสองทิศทางที่ประกอบด้วยโครงสร้างรายการที่เชื่อมโยง คิวสองทางที่เรียกว่าหมายถึงความจริงที่ว่าคุณสามารถแทรกและลบองค์ประกอบออกจากปลายทั้งสองของคิว เนื่องจากคิวสองปลายมีรายการเพิ่มเติมไปยังคิวการดำเนินการการแข่งขันจะลดลงครึ่งหนึ่งเมื่อหลายเธรดเข้าร่วมคิวในเวลาเดียวกัน เมื่อเปรียบเทียบกับคิวการปิดกั้นอื่น ๆ LinkedBlockingDeque มี addfirst, addlast, addlast, ข้อเสนอ First, OfferLast, Peekfirst, Peeklast และวิธีการอื่น ๆ วิธีการลงท้ายด้วยคำแรกหมายถึงการแทรกการได้มาหรือการลบองค์ประกอบแรกของคิวสองปลาย วิธีการที่ลงท้ายด้วยคำสุดท้ายแสดงให้เห็นว่าองค์ประกอบสุดท้ายของคิวสองปลายถูกแทรกได้รับหรือลบออก นอกจากนี้การเพิ่มวิธีการแทรกเท่ากับ AddLast และวิธีการลบการลบนั้นเทียบเท่ากับการลบ First อย่างไรก็ตามวิธีการใช้เวลาเท่ากับ Takefirst ฉันไม่รู้ว่ามันเป็นข้อผิดพลาดใน JDK และชัดเจนกว่าที่จะใช้วิธีการกับคำต่อท้ายแรกและสุดท้ายเมื่อใช้งาน ความสามารถของคิวสามารถเริ่มต้นได้เมื่อเริ่มต้น LinkedBlockingDeque เพื่อป้องกันไม่ให้บวมเมื่อมีการเพิ่มอีกครั้ง นอกจากนี้คิวการบล็อกแบบสองทิศทางสามารถใช้ในโหมด "การโจรกรรม"
ขอบคุณสำหรับการอ่านฉันหวังว่ามันจะช่วยคุณได้ ขอบคุณสำหรับการสนับสนุนเว็บไซต์นี้!