ไม่วิธีนี้ไม่จำเป็นต้องซิงโครไนซ์และคุณไม่จำเป็นต้องกำหนดวิธีการใด ๆ พวกเขาอยู่ใน ConcurrentLinkedQueue แล้วเพียงแค่ใช้พวกเขา ConcurrentLinkedQueue ทำการล็อคและการดำเนินการอื่น ๆ ทั้งหมดที่คุณต้องการภายใน โปรดิวเซอร์ของคุณเพิ่มข้อมูลลงในคิวและผู้บริโภคของคุณจะสำรวจความคิดเห็น
ขั้นแรกสร้างคิวของคุณ:
Queue<YourObject> queue = new ConcurrentLinkedQueue<YourObject>();
ตอนนี้ไม่ว่าคุณจะสร้างวัตถุผู้ผลิต / ผู้บริโภคของคุณที่ใดก็ตามให้ส่งต่อในคิวเพื่อให้พวกเขามีที่วางวัตถุ (คุณสามารถใช้ตัวตั้งค่าสำหรับสิ่งนี้แทนได้ แต่ฉันชอบทำสิ่งนี้ในตัวสร้าง):
YourProducer producer = new YourProducer(queue);
และ:
YourConsumer consumer = new YourConsumer(queue);
และเพิ่มเนื้อหาในโปรดิวเซอร์ของคุณ:
queue.offer(myObject);
และนำสิ่งต่างๆออกไปในผู้บริโภคของคุณ (หากคิวว่างเปล่าแบบสำรวจ () จะส่งคืนค่าว่างดังนั้นให้ตรวจสอบ):
YourObject myObject = queue.poll();
สำหรับข้อมูลเพิ่มเติมโปรดดูJavadoc
แก้ไข:
หากคุณต้องการบล็อกการรอให้คิวไม่ว่างคุณอาจต้องการใช้LinkedBlockingQueueและใช้เมธอด take () อย่างไรก็ตาม LinkedBlockingQueue มีความจุสูงสุด (ค่าเริ่มต้นคือ Integer.MAX_VALUE ซึ่งมากกว่าสองพันล้าน) ดังนั้นจึงอาจเหมาะสมหรือไม่ก็ได้ขึ้นอยู่กับสถานการณ์ของคุณ
หากคุณมีเธรดเพียงเธรดเดียวที่ใส่สิ่งต่างๆลงในคิวและอีกเธรดหนึ่งดึงข้อมูลออกจากคิว ConcurrentLinkedQueue อาจจะมากเกินไป ยิ่งไปกว่านั้นเมื่อคุณอาจมีหลายร้อยหรือหลายพันเธรดที่เข้าถึงคิวในเวลาเดียวกัน ความต้องการของคุณอาจได้รับการตอบสนองโดยใช้:
Queue<YourObject> queue = Collections.synchronizedList(new LinkedList<YourObject>());
ข้อดีของสิ่งนี้คือมันล็อกอินสแตนซ์ (คิว) ดังนั้นคุณสามารถซิงโครไนซ์ในคิวเพื่อให้แน่ใจว่าการดำเนินการคอมโพสิตเป็นอะตอม (ตามที่จาเร็ดอธิบาย) คุณไม่สามารถทำได้ด้วย ConcurrentLinkedQueue เนื่องจากการดำเนินการทั้งหมดเสร็จสิ้นโดยไม่มีการล็อกอินสแตนซ์ (โดยใช้ตัวแปร java.util.concurrent.atomic) คุณไม่จำเป็นต้องทำสิ่งนี้หากคุณต้องการบล็อกในขณะที่คิวว่างเปล่าเพราะการสำรวจความคิดเห็น () จะคืนค่าว่างในขณะที่คิวว่างเปล่าและการสำรวจความคิดเห็น () เป็นอะตอม ตรวจสอบเพื่อดูว่าแบบสำรวจ () ส่งคืนค่าว่างหรือไม่ หากเป็นเช่นนั้นให้รอ () แล้วลองอีกครั้ง ไม่จำเป็นต้องล็อค
สุดท้าย:
จริงๆแล้วฉันแค่ใช้ LinkedBlockingQueue ยังคงใช้งานมากเกินไปสำหรับแอปพลิเคชันของคุณ แต่โอกาสที่จะใช้ได้ดี หากมีประสิทธิภาพไม่เพียงพอ (โปรไฟล์!) คุณสามารถลองอย่างอื่นได้ตลอดเวลาและหมายความว่าคุณไม่จำเป็นต้องจัดการกับสิ่งที่ซิงโครไนซ์ใด ๆ :
BlockingQueue<YourObject> queue = new LinkedBlockingQueue<YourObject>();
queue.put(myObject);
YourObject myObject = queue.take();
อย่างอื่นเหมือนกันหมด Put อาจไม่บล็อกเพราะคุณไม่น่าจะใส่วัตถุสองพันล้านชิ้นลงในคิว