JavaRush /จาวาบล็อก /Random-TH /ตัวอย่าง SynchronousQueue ใน Java - การแก้ปัญหา Producer ...
profeg
ระดับ

ตัวอย่าง SynchronousQueue ใน Java - การแก้ปัญหา Producer Consumer

เผยแพร่ในกลุ่ม
ตัวอย่าง 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 ดังที่ฉันได้กล่าวไว้ข้างต้น ไม่มีอะไรดีไปกว่าปัญหาระหว่างผู้ผลิตและผู้บริโภคในการทำความเข้าใจการสื่อสารระหว่างเธรดในภาษาการเขียนโปรแกรมใดๆ ในปัญหานี้ เธรดหนึ่งทำหน้าที่เป็นผู้ผลิตที่สร้างเหตุการณ์และงาน และเธรดอื่นทำหน้าที่เป็นผู้บริโภค บัฟเฟอร์ที่ใช้ร่วมกันใช้เพื่อถ่ายโอนข้อมูลจากผู้ผลิตไปยังผู้บริโภค ความยากในการแก้ปัญหานี้เกิดขึ้นในกรณีร้ายแรง เช่น เมื่อผู้ผลิตถูกบังคับให้รอเพราะ... บัฟเฟอร์เต็มหรือผู้บริโภคถูกบังคับให้รอเนื่องจาก บัฟเฟอร์ว่างเปล่า เรื่องนี้แก้ไขได้ง่ายเพราะ... คิวการบล็อกไม่เพียงแต่จัดเตรียมบัฟเฟอร์สำหรับการจัดเก็บข้อมูลเท่านั้น แต่ยังรวมถึงการควบคุมการไหล การบล็อกเธรดที่เรียกใช้เมธอด put() (Producer) หากบัฟเฟอร์เต็ม และการบล็อกเธรดที่เรียกใช้เมธอด take() (Consumer) หาก บัฟเฟอร์ว่างเปล่า ตอนนี้เราจะแก้ไขปัญหาเดียวกันนี้โดยใช้ SynchronousQueue ซึ่งเป็น คอลเลกชันแบบขนานชนิดพิเศษที่มีความจุเป็นศูนย์ ในตัวอย่างต่อไปนี้ เรามีสองเธรดที่เรียกว่าPRODUCERและCONSUMER (ตั้งชื่อให้กับเธรดเสมอซึ่งเป็นรูปแบบที่ดีมากของการเขียนโปรแกรมแบบมัลติเธรด) เธรดแรกโพสต์คะแนนในเกม และเธรดที่สองจะใช้มัน คะแนนในเกมไม่มีอะไรมากไปกว่าวัตถุประเภทสตริง แต่ถ้าคุณรันโปรแกรมด้วยประเภทอื่น คุณจะไม่สังเกตเห็นความแตกต่างใดๆ เพื่อทำความเข้าใจวิธีการทำงานของ SynchronousQueue และวิธีแก้ปัญหาผู้ผลิต-ผู้บริโภค คุณต้อง: รันโปรแกรมสำหรับการดีบัก (ดีบัก) ในสภาพแวดล้อม Eclipseหรือเพียงแค่เริ่มเธรดผู้ผลิตโดยใส่เครื่องหมายความคิดเห็น Consumer.start(); หากเธรดผู้บริโภคไม่ได้ทำงานอยู่ เธรดผู้ผลิตจะถูกบล็อกที่ Queu.put(event); หากทำงานอยู่ คุณจะไม่เห็นผู้ผลิต [PRODUCER] เผยแพร่กิจกรรม :FOUR สิ่งนี้เกิดขึ้นเพราะว่า พฤติกรรมเฉพาะของ SynchronousQueue ซึ่งช่วยให้มั่นใจว่าข้อมูลการโพสต์เธรดจะถูกบล็อกจนกว่าเธรดอื่นจะรับข้อมูลไป และในทางกลับกัน คุณสามารถทดสอบโค้ดที่เหลือได้โดยการใส่ความคิดเห็นที่producer.start(); และเริ่มต้นเฉพาะเธรดผู้บริโภคเท่านั้น หากคุณศึกษาอย่างรอบคอบว่าโปรแกรมส่งออกอะไรออกมา คุณจะสังเกตเห็นว่าลำดับของเอาต์พุตกลับกัน ดูเหมือนว่า เธรด [CONSUMER] จะนำข้อมูลก่อนที่ เธรด [PRODUCER]จะสร้างขึ้นมา เนื่องจาก SynchronousQueue ไม่รับประกันการเข้าคิวตามค่าเริ่มต้น แต่มีกฎความเป็นธรรมที่กำหนดการเข้าถึงเธรดตามลำดับ FIFO คุณสามารถเปิดใช้งานกฎเหล่านี้ได้โดยการส่งค่าจริงไปยัง ตัวสร้าง SynchronousQueue ที่โอเวอร์โหลดดังนี้: 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 มีประโยชน์มากในการส่งข้อมูลจากเธรดหนึ่งไปยังอีกเธรดหนึ่งในลักษณะซิงโครไนซ์ คิวนี้ไม่มีความสามารถและถูกบล็อกจนกว่าเธรดอื่นจะว่าง

  1. SynchronousQueue บล็อก และจนกว่าเธรดหนึ่งพร้อมที่จะรับข้อมูล อีกเธรดจะพยายามใส่ข้อมูล
  2. SynchronousQueue ไม่มีโวลุ่ม นั่นคือไม่มีข้อมูล
  3. SynchronousQueue ใช้เพื่อใช้กลยุทธ์การส่งต่อคิว โดยที่เธรดส่งผ่านการควบคุมไปยังเธรดที่รอ หรือสร้างขึ้นใหม่หากได้รับอนุญาต มิฉะนั้น การควบคุมจะไม่ถูกถ่ายโอน
  4. คิวนี้ไม่อนุญาตให้มีข้อมูลว่าง ความพยายามที่จะเพิ่มองค์ประกอบ null จะทำให้เกิดNullPointerException
  5. หากคุณใช้วิธีการอื่นจากคอลเลกชัน (เช่น มี) SynchronousQueue จะทำงานเหมือนกับคอลเลกชันเปล่า
  6. คุณไม่สามารถใช้วิธี peek ของ SynchronousQueue ได้เนื่องจากองค์ประกอบมีอยู่เฉพาะเมื่อคุณพยายามลบออกเท่านั้น นอกจากนี้ คุณจะไม่สามารถแทรกองค์ประกอบได้ (โดยใช้วิธีการใดๆ) จนกว่าเธรดอื่นจะพยายามลบออก
  7. คุณจะไม่สามารถใช้ตัววนซ้ำสำหรับ SynchronousQueue ได้เนื่องจาก... มันไม่มีองค์ประกอบ
  8. SynchronousQueue สามารถสร้างได้ด้วยกฎที่ยุติธรรม ซึ่งรับประกันการเข้าถึงเธรดตามลำดับ FIFO
บางทีนี่อาจเป็นข้อมูลเกี่ยวกับSynchronousQueue ใน Java เราได้ดูคุณสมบัติพิเศษบางอย่างของคอลเลกชันแบบมัลติเธรดนี้ และเรียนรู้วิธีการแก้ปัญหาแบบคลาสสิกของผู้ผลิตและผู้บริโภคโดยใช้ SynchronousQueue ใน Java อย่างไรก็ตาม การเรียกมันว่า Queue นั้นไม่ถูกต้องทั้งหมด เพราะ... มันไม่มีองค์ประกอบ การเรียกเพื่อใส่() จะไม่เสร็จสมบูรณ์จนกว่าการเรียกเธรดอื่นจะใช้() เป็นการถูกต้องมากกว่าที่จะคิดว่ามันเป็นสถานที่พบปะของเธรดที่พวกเขาแชร์วัตถุกัน กล่าวอีกนัยหนึ่ง มันเป็นยูทิลิตี้สำหรับการส่งผ่านอ็อบเจ็กต์แบบซิงโครไนซ์ใน Java ซึ่งอาจเป็นทางเลือกที่ปลอดภัยกว่าเมธอดwait and notify
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION