คิวที่ไม่ปิดกั้น

การใช้งานคิวที่ปลอดภัยสำหรับ เธรดและที่สำคัญที่สุดคือไม่บล็อกบนโหนดที่เชื่อมโยง
ConcurrentLinkedQueue<E> - ใช้อัลกอริทึมแบบไม่ต้องรอที่ปรับให้ทำงานร่วมกับตัวรวบรวมขยะ อัลกอริทึมนี้ค่อนข้างมีประสิทธิภาพและรวดเร็วมาก เนื่องจากสร้างขึ้นจาก CAS เมธอด size()สามารถรันได้เป็นเวลานาน ดังนั้นจึงไม่ควรดึงเมธอดตลอดเวลา
ConcurrentLinkedDeque<E> - Deque หมายถึงคิวสิ้นสุดสองครั้ง ซึ่งหมายความว่าสามารถเพิ่มและดึงข้อมูลจากทั้งสองด้านได้ ดังนั้น คลาสจึงรองรับการทำงานทั้งสองโหมด: FIFO (เข้าก่อนออกก่อน) และ LIFO (เข้าก่อนออกก่อน)
ในทางปฏิบัติ ควรใช้ ConcurrentLinkedDequeถ้า LIFO มีความจำเป็นจริงๆ เนื่องจากโหนดเป็นแบบสองทิศทาง คลาสนี้จึงสูญเสียประสิทธิภาพไปครึ่งหนึ่งเมื่อเทียบกับConcurrentLinkedQueue
import java.util.concurrent.ConcurrentLinkedQueue;
public class ConcurrentLinkedQueueExample {
public static void main(String[] args) {
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
Thread producer = new Thread(new Producer(queue));
Thread consumer = new Thread(new Consumer(queue));
producer.start();
consumer.start();
}
}
class Producer implements Runnable {
ConcurrentLinkedQueue<String> queue;
Producer(ConcurrentLinkedQueue<String> queue){
this.queue = queue;
}
public void run() {
System.out.println("Class for adding items to the queue");
try {
for (int i = 1; i < 5; i++) {
queue.add("Item #" + i);
System.out.println("Added: Item #" + i);
Thread.sleep(300);
}
} catch (InterruptedException ex) {
ex.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
class Consumer implements Runnable {
ConcurrentLinkedQueue<String> queue;
Consumer(ConcurrentLinkedQueue<String> queue){
this.queue = queue;
}
public void run() {
String str;
System.out.println("Class for getting items from the queue");
for (int x = 0; x < 5; x++) {
while ((str = queue.poll()) != null) {
System.out.println("Pulled out: " + str);
}
try {
Thread.sleep(600);
} catch (InterruptedException ex) {
ex.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
}
การบล็อกคิว

อินเทอร์เฟซBlockingQueue<E> - หากมีข้อมูลจำนวนมาก แสดงว่าConcurrentLinkedQueueไม่เพียงพอ
เมื่อเธรดล้มเหลวในการทำงาน คุณสามารถรับOutOfMemmoryException ได้อย่าง ง่ายดาย และเพื่อไม่ให้กรณีดังกล่าวเกิดขึ้น เรามีBlockingQueue สำหรับการทำงาน กับวิธีการต่างๆ ในการเติมและทำงานกับคิวและการล็อกแบบมีเงื่อนไข
BlockingQueueไม่รู้จักองค์ประกอบ null และพ่น NullPointerExceptionเมื่อพยายามเพิ่มหรือรับองค์ประกอบดังกล่าว วิธีการสำรวจจะส่งคืนองค์ประกอบ null หากไม่มีการวางองค์ประกอบในคิวภายในระยะหมดเวลา
BlockingQueue<E> การใช้งาน
มาดู การใช้งาน BlockingQueue ของเราอย่างละเอียดยิ่งขึ้น :
ArrayBlockingQueue<E>เป็นคลาสคิวการบล็อกที่สร้างขึ้นบนบัฟเฟอร์วงแหวนแบบคลาสสิก ที่นี่เรามีโอกาสที่จะจัดการ "ความซื่อสัตย์" ของล็อค หากยุติธรรม=เท็จ (ค่าเริ่มต้น) ลำดับของเธรดจะไม่รับประกัน
DelayQueue<E ขยาย Delayed>เป็นคลาสที่อนุญาตให้คุณดึงองค์ประกอบจากคิวหลังจากการหน่วงเวลาที่กำหนดเท่านั้น ซึ่งกำหนดไว้ในแต่ละองค์ประกอบผ่านเมธอดgetDelayของอินเทอร์เฟซ Delayed
LinkedBlockingQueue<E>เป็นคิวบล็อกบนโหนดที่เชื่อมโยง ซึ่งใช้งานบนอัลกอริทึม “คิวล็อคสองคิว”: ล็อคแรกใช้สำหรับเพิ่ม ส่วนที่สองใช้สำหรับดึงองค์ประกอบจากคิว เนื่องจากการล็อก เมื่อเทียบกับ ArrayBlockingQueueคลาสนี้จึงมีประสิทธิภาพสูง แต่ต้องใช้หน่วยความจำมากกว่า ขนาดคิวถูกตั้งค่าผ่านตัวสร้างและเท่ากับ Integer.MAX_VALUE โดยค่าเริ่มต้น
PriorityBlockingQueue<E>เป็น wrapper แบบหลายเธรดเหนือ PriorityQueue ตัวเปรียบเทียบมีหน้าที่รับผิดชอบตรรกะที่องค์ประกอบจะถูกเพิ่มเข้าไป องค์ประกอบที่เล็กที่สุดจะออกมาก่อน
SynchronousQueue<E> - คิวทำงานตามหลักการ FIFO (เข้าก่อนออกก่อน) การดำเนินการแทรกแต่ละครั้งจะบล็อกเธรด "ผู้ผลิต" จนกว่าเธรด "ผู้บริโภค" จะดึงองค์ประกอบออกจากคิว และในทางกลับกัน "ผู้บริโภค" จะรอจนกว่า "ผู้ผลิต" จะแทรกองค์ประกอบ
BlockingDeque<E>เป็นอินเทอร์เฟซที่อธิบายวิธีการเพิ่มเติมสำหรับคิวการบล็อกแบบสองทิศทาง สามารถแทรกและดึงข้อมูลจากทั้งสองด้านของคิว
LinkedBlockingDeque<E>เป็นคิวบล็อกแบบสองทิศทางบนโหนดที่เชื่อมโยง ใช้งานเป็นรายการแบบสองทิศทางอย่างง่ายด้วยการล็อกเพียงครั้งเดียว ขนาดคิวถูกตั้งค่าผ่านตัวสร้างและเท่ากับ Integer.MAX_VALUE โดยค่าเริ่มต้น
TransferQueue<E> - อินเทอร์เฟซมีความน่าสนใจตรงที่เมื่อมีการเพิ่มองค์ประกอบลงในคิว เป็นไปได้ที่จะบล็อกการแทรกเธรด Producerจนกว่า เธรด Consumer อื่น จะดึงองค์ประกอบจากคิว คุณยังสามารถเพิ่มการตรวจสอบสำหรับการหมด เวลาที่กำหนด หรือตั้งค่าการตรวจสอบสำหรับผู้บริโภคที่รอดำเนินการ เป็นผลให้เราได้รับกลไกการถ่ายโอนข้อมูลพร้อมรองรับข้อความอะซิงโครนัสและซิงโครนัส
LinkedTransferQueue<E>เป็นการนำ TransferQueueไปใช้ตามอัลกอริทึม Dual Queues พร้อม Slack ใช้งานหนักของ CAS (ดูด้านบน) และการจอดเธรดเมื่อไม่ได้ใช้งาน
GO TO FULL VERSION