ความแตกต่างระหว่าง Consumer / Producer และ Observer / Observable


15

ฉันกำลังทำงานเกี่ยวกับการออกแบบแอปพลิเคชันที่ประกอบด้วยสามส่วน:

  • เธรดเดียวที่เฝ้าดูเหตุการณ์บางอย่างที่เกิดขึ้น (การสร้างไฟล์คำขอภายนอก ฯลฯ )
  • เธรดผู้ปฏิบัติงาน N ที่ตอบสนองต่อเหตุการณ์เหล่านี้โดยการประมวลผล (ผู้ปฏิบัติงานแต่ละกระบวนการและใช้เหตุการณ์เดียวและการประมวลผลอาจใช้เวลาแปรผัน)
  • คอนโทรลเลอร์ที่จัดการเธรดเหล่านั้นและจัดการข้อผิดพลาด (การรีสตาร์ทเธรดการบันทึกผลลัพธ์)

แม้ว่านี่จะค่อนข้างพื้นฐานและไม่ยากที่จะนำมาใช้ แต่ฉันก็สงสัยว่ามันจะเป็นวิธีที่ "ถูกต้อง" (ในกรณีที่เป็นรูปธรรมนี้ใน Java แต่คำตอบที่เป็นนามธรรมก็สูงขึ้นเช่นกัน) กลยุทธ์ทั้งสองมาถึงใจ:

  • ผู้สังเกตการณ์ / สังเกตได้:ผู้สังเกตการณ์จะเฝ้าสังเกตด้ายดู ในกรณีที่มีเหตุการณ์เกิดขึ้นคอนโทรลเลอร์จะได้รับแจ้งและสามารถมอบหมายงานใหม่ให้กับเธรดอิสระจากกลุ่มเธรดแคชที่ใช้ซ้ำได้ (หรือรอและแคชงานในคิว FIFO หากเธรดทั้งหมดไม่ว่างในขณะนี้) เธรดผู้ปฏิบัติงานใช้ Callable และส่งคืนผลลัพธ์ที่สำเร็จพร้อมกับผลลัพธ์ (หรือค่าบูลีน) หรือส่งคืนพร้อมข้อผิดพลาดในกรณีนี้ผู้ควบคุมอาจตัดสินใจว่าจะทำอย่างไร (ขึ้นอยู่กับลักษณะของข้อผิดพลาดที่เกิดขึ้น)

  • ผู้ผลิต / ผู้บริโภค : เธรดการเฝ้าดูที่ใช้ร่วมกัน BlockingQueue กับตัวควบคุม (เหตุการณ์คิว) และตัวควบคุมที่ใช้ร่วมกันสองกับคนงานทั้งหมด (งานคิวและผลคิว) ในกรณีที่เกิดเหตุการณ์ด้ายเฝ้าดูทำให้วัตถุงานในคิวเหตุการณ์ คอนโทรลเลอร์ใช้งานใหม่จาก event-queue ตรวจสอบและวางไว้ใน task-queue ผู้ปฏิบัติงานแต่ละคนรองานใหม่และรับ / ใช้งานจากคิวงาน (มาก่อนได้รับก่อนจัดการโดยคิวเอง) วางผลลัพธ์หรือข้อผิดพลาดกลับเข้าไปในคิวผลลัพธ์ ในที่สุดตัวควบคุมสามารถดึงผลลัพธ์จากคิวผลลัพธ์และทำตามขั้นตอนในกรณีที่เกิดข้อผิดพลาด

ผลลัพธ์สุดท้ายของวิธีการทั้งสองมีความคล้ายคลึงกัน แต่แต่ละวิธีมีความแตกต่างกันเล็กน้อย:

ด้วย Observers การควบคุมเธรดโดยตรงและแต่ละงานมีสาเหตุมาจากผู้ทำงานใหม่ที่วางไข่โดยเฉพาะ ค่าโสหุ้ยสำหรับการสร้างเธรดอาจสูงขึ้น แต่ไม่มากต้องขอบคุณพูลเธรดที่แคช ในทางกลับกันรูปแบบของ Observer จะลดลงเป็น Observer เดียวแทนที่จะเป็นหลาย ๆ แบบซึ่งไม่ใช่สิ่งที่ถูกออกแบบมาอย่างแท้จริง

กลยุทธ์คิวดูเหมือนจะขยายได้ง่ายขึ้นตัวอย่างเช่นการเพิ่มผู้ผลิตหลายรายแทนที่จะเป็นผู้ผลิตที่ตรงไปตรงมาและไม่ต้องการการเปลี่ยนแปลงใด ๆ ข้อเสียคือเธรดทั้งหมดจะทำงานอย่างไม่มีกำหนดแม้ว่าจะไม่ได้ทำงานเลยก็ตามและการจัดการข้อผิดพลาด / ผลลัพธ์ไม่ได้ดูสวยงามเท่าโซลูชั่นแรก

อะไรคือแนวทางที่เหมาะสมที่สุดในสถานการณ์นี้และทำไม ฉันพบว่ามันยากที่จะหาคำตอบของคำถามนี้ทางออนไลน์เพราะตัวอย่างส่วนใหญ่จะจัดการกับกรณีที่ชัดเจนเช่นการปรับปรุงหลายหน้าต่างด้วยค่าใหม่ในกรณีผู้สังเกตการณ์หรือการประมวลผลกับผู้บริโภคและผู้ผลิตหลายราย ข้อมูลใด ๆ ที่ชื่นชมอย่างมาก

คำตอบ:


10

คุณค่อนข้างใกล้กับการตอบคำถามของคุณเอง :)

ในรูปแบบ Observable / Observer (สังเกตการพลิก) มีสามสิ่งที่ควรคำนึงถึง:

  1. โดยทั่วไปการแจ้งเตือนการเปลี่ยนแปลงคือ 'ส่วนของข้อมูล' จะอยู่ในระดับที่สังเกตได้
  2. สังเกตอยู่
  3. ผู้สังเกตการณ์จะต้องรู้จักกับผู้สังเกตการณ์ที่มีอยู่เดิม (หรืออื่น ๆ ที่พวกเขาไม่มีอะไรจะสังเกต)

เมื่อรวมประเด็นเหล่านี้เข้าด้วยกันสิ่งที่บอกเป็นนัยก็คือผู้สังเกตการณ์รู้ว่าองค์ประกอบปลายน้ำคืออะไรคือผู้สังเกตการณ์ การไหลของข้อมูลนั้นมาจากสิ่งที่สังเกตได้ - ผู้สังเกตการณ์เพียง 'มีชีวิตและตาย' จากสิ่งที่พวกเขาสังเกต

ในรูปแบบ Producer / Consumer คุณจะได้รับการโต้ตอบที่แตกต่างกันมาก:

  1. โดยทั่วไปแล้วน้ำหนักบรรทุกนั้นเป็นอิสระจากผู้ผลิตที่รับผิดชอบในการผลิต
  2. ผู้ผลิตไม่ทราบว่าผู้บริโภคใช้งานอย่างไรหรือเมื่อใด
  3. ผู้บริโภคไม่จำเป็นต้องรู้จักผู้ผลิตของน้ำหนักบรรทุก

ตอนนี้การไหลของข้อมูลถูกตัดอย่างสมบูรณ์ระหว่างผู้ผลิตและผู้บริโภค - ผู้ผลิตทั้งหมดรู้ว่ามันมีเอาท์พุทและผู้บริโภคทุกคนรู้ว่ามันมีอินพุต ที่สำคัญหมายความว่าผู้ผลิตและผู้บริโภคสามารถดำรงอยู่ได้อย่างสมบูรณ์โดยไม่ต้องมีที่อื่น

อีกความแตกต่างที่ไม่ให้ลึกซึ้งก็คือว่าผู้สังเกตการณ์หลายบนเดียวกันที่สังเกตมักจะได้รับส่วนของข้อมูลเดียวกัน (เว้นแต่จะมีการดำเนินการที่ไม่เป็นทางการ) ในขณะที่ผู้บริโภคหลายปิดเดียวกันผู้ผลิตอาจจะไม่ ขึ้นอยู่กับว่าตัวกลางเป็นวิธีคล้ายคิวหรือคล้ายหัวข้อ อดีตส่งข้อความที่แตกต่างกันสำหรับผู้บริโภคแต่ละรายในขณะที่ผู้บริโภคหลังมั่นใจว่า (หรือพยายาม) ที่ผู้บริโภคทั้งหมดดำเนินการตามข้อความต่อ

เพื่อให้พอดีกับแอปพลิเคชันของคุณ:

  • ในรูปแบบ Observable / Observer เมื่อใดก็ตามที่เธรดการรับชมของคุณกำลังเริ่มต้นต้องทราบวิธีการแจ้งคอนโทรลเลอร์ ในฐานะผู้สังเกตการณ์ตัวควบคุมมีแนวโน้มที่จะรอการแจ้งเตือนจากเธรดการเฝ้าดูก่อนที่จะอนุญาตให้เธรดจัดการการเปลี่ยนแปลง
  • ในรูปแบบผู้ผลิต / ผู้บริโภคเธรดการเฝ้าดูของคุณจำเป็นต้องทราบว่ามีคิวเหตุการณ์แล้วเท่านั้นและโต้ตอบกับสิ่งนั้นเท่านั้น ในฐานะผู้บริโภคตัวควบคุมจะทำการสำรวจคิวเหตุการณ์และเมื่อได้รับ payload ใหม่แล้วจะช่วยให้เธรดจัดการได้

ดังนั้นเพื่อตอบคำถามของคุณโดยตรง: หากคุณต้องการรักษาระดับการแยกระหว่างเธรดการดูและคอนโทรลเลอร์ของคุณในระดับที่คุณสามารถใช้งานได้อย่างอิสระคุณควรมีแนวโน้มไปที่รูปแบบ Producer / Consumer


2
ขอบคุณสำหรับคำตอบโดยละเอียด น่าเสียดายที่ฉันไม่สามารถลงคะแนนได้เนื่องจากขาดชื่อเสียงดังนั้นฉันจึงทำเครื่องหมายว่าเป็นโซลูชันแทน อิสรภาพทางโลกระหว่างทั้งสองส่วนที่คุณพูดถึงเป็นสิ่งที่ดีที่ฉันยังไม่เคยนึกถึงมาก่อน คิวสามารถจัดการการปะทุสั้น ๆ ของเหตุการณ์จำนวนมากที่มีการหยุดแบบยาวระหว่างดีกว่าการดำเนินการโดยตรงหลังจากเหตุการณ์ถูกสังเกต (ถ้านับจำนวนเธรดสูงสุดคงที่และค่อนข้างต่ำ) จำนวนเธรดสามารถเพิ่ม / ลดแบบไดนามิกได้โดยขึ้นอยู่กับจำนวนรายการคิวปัจจุบัน
183536

@ user183536 ไม่มีปัญหายินดีช่วยเหลือ! :)
hjk
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.