ตัวอย่าง SynchronousQueue ใน Java - การแก้ปัญหา Producer Consumer
SynchronousQueue เป็น BlockingQueue ชนิดพิเศษที่การดำเนินการแทรกแต่ละรายการต้องรอคำสั่งลบที่เกี่ยวข้องในเธรดอื่น และในทางกลับกัน เมื่อคุณเรียกใช้เมธอด put()บน SynchronousQueue มันจะบล็อกจนกว่าเธรดอื่นจะนำองค์ประกอบนั้นไป ดังนั้น หากเธรดอื่นพยายามลบองค์ประกอบออกจากเธรดนั้น และไม่มีองค์ประกอบนั้นอยู่ เธรดนั้นจะบล็อกจนกว่าเธรดอื่นจะวางองค์ประกอบนั้นไว้ในคิว คุณสามารถนึกถึง SynchronousQueue ในฐานะนักกีฬา ( thread ) ที่วิ่งด้วยคบเพลิงโอลิมปิก เขาวิ่งด้วยคบเพลิง (วัตถุที่กำลังส่งต่อ) และส่งต่อไปยังนักกีฬาอีกคนที่รออยู่อีกด้านหนึ่ง หากคุณใส่ใจกับชื่อ คุณจะเข้าใจว่า SynchronousQueue ได้รับการตั้งชื่อเช่นนั้นด้วยเหตุผล โดยจะถ่ายโอนข้อมูลแบบซิงโครนัสไปยังเธรดอื่น มันรอให้ใครบางคนรับข้อมูลแทนที่จะใส่เข้าและออก (การดำเนินการแบบอะซิงโครนัส) หากคุณคุ้นเคยกับ CSP และ Ada คุณจะรู้ว่าคิวที่ซิงโครไนซ์นั้นคล้ายคลึงกับการประชุมของเธรด เหมาะอย่างยิ่งสำหรับโครงสร้างการถ่ายโอนการควบคุมซึ่งอ็อบเจ็กต์ที่ทำงานในเธรดหนึ่งต้องซิงโครไนซ์กับอ็อบเจ็กต์ในอีกเธรดหนึ่งเพื่อส่งข้อมูล เหตุการณ์ หรืองานบางอย่างไปให้ ในบท ช่วยสอนการเขียนโปรแกรมแบบมัลติเธรดก่อนหน้านี้ เราได้เรียนรู้วิธีการแก้ปัญหาผู้ผลิต-ผู้บริโภคโดยใช้ เมธอด wait and notifyและBlockingQueue ตอนนี้เราจะได้เรียนรู้วิธีใช้รูปแบบผู้ผลิต-ผู้บริโภคโดยใช้ SynchronousQueue คลาสนี้ยังสนับสนุนพฤติกรรมที่เป็นธรรมในการสั่งซื้อการรอของเธรดของผู้ผลิตและผู้บริโภค ตามค่าเริ่มต้น จะไม่รับประกันการสั่งซื้อนี้ อย่างไรก็ตาม คิวที่สร้างขึ้นด้วยคุณสมบัติยุติธรรมจะรับประกันการเข้าถึงเธรดในคิว FIFO (Firs In First Out)ผู้ผลิต/ผู้บริโภคที่ใช้ SynchronousQueue ใน Java
![ตัวอย่าง SynchronousQueue ใน Java - การแก้ปัญหา Producer Consumer - 1](https://cdn.javarush.com/images/article/cadfb899-3d92-40d8-9d6b-19836b3d44a3/1024.jpeg)
import java.util.concurrent.SynchronousQueue; /** * Java Program to solve Producer Consumer problem using SynchronousQueue. A * call to put() will block until there is a corresponding thread to take() that * element. * * @author Javin Paul */ public class SynchronousQueueDemo{ public static void main(String args[]) { final SynchronousQueue
queue = new SynchronousQueue
(); Thread producer = new Thread("PRODUCER") { public void run() { String event = "FOUR"; try { queue.put(event); // thread will block here System.out.printf("[%s] published event : %s %n", Thread .currentThread() .getName(), event); } catch (InterruptedException e) { e.printStackTrace(); } } }; producer.start(); // starting publisher thread Thread consumer = new Thread("CONSUMER") { public void run() { try { String event = queue.take(); // thread will block here System.out.printf("[%s] consumed event : %s %n", Thread .currentThread() .getName(), event); } catch (InterruptedException e) { e.printStackTrace(); } } }; consumer.start(); // starting consumer thread } } Output: [CONSUMER] consumed event : FOUR [PRODUCER] published event : FOUR
new SynchronousQueue(boolean fair).
สิ่งที่คุณต้องจำเกี่ยวกับ SynchronousQueue ใน Java
ต่อไปนี้เป็นคุณสมบัติที่สำคัญบางประการของคิวการบล็อกชนิดพิเศษใน Java มีประโยชน์มากในการส่งข้อมูลจากเธรดหนึ่งไปยังอีกเธรดหนึ่งในลักษณะซิงโครไนซ์ คิวนี้ไม่มีความสามารถและถูกบล็อกจนกว่าเธรดอื่นจะว่าง
- SynchronousQueue บล็อก และจนกว่าเธรดหนึ่งพร้อมที่จะรับข้อมูล อีกเธรดจะพยายามใส่ข้อมูล
- SynchronousQueue ไม่มีโวลุ่ม นั่นคือไม่มีข้อมูล
- SynchronousQueue ใช้เพื่อใช้กลยุทธ์การส่งต่อคิว โดยที่เธรดส่งผ่านการควบคุมไปยังเธรดที่รอ หรือสร้างขึ้นใหม่หากได้รับอนุญาต มิฉะนั้น การควบคุมจะไม่ถูกถ่ายโอน
- คิวนี้ไม่อนุญาตให้มีข้อมูลว่าง ความพยายามที่จะเพิ่มองค์ประกอบ null จะทำให้เกิดNullPointerException
- หากคุณใช้วิธีการอื่นจากคอลเลกชัน (เช่น มี) SynchronousQueue จะทำงานเหมือนกับคอลเลกชันเปล่า
- คุณไม่สามารถใช้วิธี peek ของ SynchronousQueue ได้เนื่องจากองค์ประกอบมีอยู่เฉพาะเมื่อคุณพยายามลบออกเท่านั้น นอกจากนี้ คุณจะไม่สามารถแทรกองค์ประกอบได้ (โดยใช้วิธีการใดๆ) จนกว่าเธรดอื่นจะพยายามลบออก
- คุณจะไม่สามารถใช้ตัววนซ้ำสำหรับ SynchronousQueue ได้เนื่องจาก... มันไม่มีองค์ประกอบ
- SynchronousQueue สามารถสร้างได้ด้วยกฎที่ยุติธรรม ซึ่งรับประกันการเข้าถึงเธรดตามลำดับ FIFO
GO TO FULL VERSION