Sự khác biệt giữa Người tiêu dùng / Nhà sản xuất và Người quan sát / Có thể quan sát được


15

Tôi đang làm việc để thiết kế một ứng dụng bao gồm ba phần:

  • một luồng duy nhất theo dõi các sự kiện nhất định xảy ra (tạo tệp, yêu cầu bên ngoài, v.v.)
  • N luồng công nhân phản ứng với các sự kiện này bằng cách xử lý chúng (mỗi công nhân xử lý và tiêu thụ một sự kiện duy nhất và quá trình xử lý có thể mất thời gian khác nhau)
  • một bộ điều khiển quản lý các luồng đó và xử lý lỗi (khởi động lại các luồng, ghi nhật ký kết quả)

Mặc dù điều này khá cơ bản và không khó thực hiện, tôi tự hỏi đâu là cách "đúng" để làm điều đó (trong trường hợp cụ thể này trong Java, nhưng các câu trả lời trừu tượng cao hơn cũng được đánh giá cao). Hai chiến lược xuất hiện trong tâm trí:

  • Observer / Observable: Chuỗi xem được quan sát bởi bộ điều khiển. Trong trường hợp có sự kiện xảy ra, bộ điều khiển sau đó sẽ được thông báo và có thể gán tác vụ mới cho luồng miễn phí từ nhóm luồng được lưu trong bộ nhớ cache có thể sử dụng lại (hoặc chờ và lưu trữ các tác vụ trong hàng đợi FIFO nếu tất cả các luồng hiện đang bận). Các luồng công nhân thực hiện Callable và trả về thành công với kết quả (hoặc giá trị boolean) hoặc trả về có lỗi, trong trường hợp đó, bộ điều khiển có thể quyết định nên làm gì (tùy thuộc vào bản chất của lỗi đã xảy ra).

  • Nhà sản xuất / Người tiêu dùng : Chuỗi xem chia sẻ BlockingQueue với bộ điều khiển (hàng đợi sự kiện) và bộ điều khiển chia sẻ hai với tất cả các công nhân (hàng đợi tác vụ và hàng đợi kết quả). Trong trường hợp của một sự kiện, luồng xem sẽ đặt một đối tượng tác vụ vào hàng đợi sự kiện. Bộ điều khiển nhận các tác vụ mới từ hàng đợi sự kiện, xem xét chúng và đặt chúng vào hàng đợi tác vụ. Mỗi công nhân chờ đợi các nhiệm vụ mới và nhận / tiêu thụ chúng từ hàng đợi nhiệm vụ (lần đầu tiên được phục vụ trước, được quản lý bởi chính hàng đợi), đưa kết quả hoặc lỗi trở lại vào hàng đợi kết quả. Cuối cùng, bộ điều khiển có thể truy xuất kết quả từ hàng đợi kết quả và thực hiện theo các bước trong trường hợp có lỗi.

Kết quả cuối cùng của cả hai phương pháp đều tương tự nhau, nhưng chúng đều có những khác biệt nhỏ:

Với Người quan sát, việc kiểm soát các luồng là trực tiếp và mỗi tác vụ được quy cho một công nhân sinh sản mới cụ thể. Chi phí để tạo chủ đề có thể cao hơn, nhưng không nhiều nhờ vào nhóm chủ đề được lưu trữ. Mặt khác, mẫu Observer được thu gọn thành một Observer duy nhất thay vì nhiều, đó không chính xác là mẫu được thiết kế cho.

Chiến lược xếp hàng dường như dễ dàng mở rộng hơn, ví dụ: thêm nhiều nhà sản xuất thay vì một nhà sản xuất đơn giản và không yêu cầu bất kỳ thay đổi nào. Nhược điểm là tất cả các luồng sẽ chạy vô thời hạn, ngay cả khi không thực hiện bất kỳ công việc nào, và xử lý lỗi / kết quả trông không thanh lịch như trong giải pháp đầu tiên.

Điều gì sẽ là cách tiếp cận phù hợp nhất trong tình huống này và tại sao? Tôi đã gặp khó khăn khi tìm câu trả lời cho câu hỏi này trực tuyến, vì hầu hết các ví dụ chỉ xử lý các trường hợp rõ ràng, như cập nhật nhiều cửa sổ với giá trị mới trong trường hợp Observer hoặc xử lý với nhiều người tiêu dùng và nhà sản xuất. Bất kỳ đầu vào được đánh giá rất cao.

Câu trả lời:


10

Bạn khá gần gũi để trả lời câu hỏi của riêng bạn. :)

Trong mẫu Quan sát / Quan sát viên (lưu ý lật), có ba điều cần lưu ý:

  1. Nói chung, thông báo về sự thay đổi, tức là 'tải trọng', có thể quan sát được.
  2. Các quan sát tồn tại .
  3. Người quan sát phải được biết đến những gì thể quan sát được (nếu không họ không có gì để quan sát).

Bằng cách kết hợp các điểm này, điều được ngụ ý là người quan sát có thể biết các thành phần hạ nguồn của nó là gì, tức là các nhà quan sát. Luồng dữ liệu vốn được điều khiển từ những người quan sát được - những người quan sát chỉ đơn giản là "sống và chết" bởi những gì họ đang quan sát.

Trong mẫu Nhà sản xuất / Người tiêu dùng, bạn có được sự tương tác rất khác nhau:

  1. Nói chung, tải trọng tồn tại độc lập với nhà sản xuất chịu trách nhiệm sản xuất nó.
  2. Các nhà sản xuất không biết làm thế nào hoặc khi nào người tiêu dùng hoạt động.
  3. Người tiêu dùng không cần phải biết nhà sản xuất của tải trọng.

Luồng dữ liệu hiện đã bị cắt đứt hoàn toàn giữa nhà sản xuất và người tiêu dùng - tất cả các nhà sản xuất đều biết rằng nó có đầu ra và tất cả những gì người tiêu dùng biết là nó có đầu vào. Điều quan trọng, điều này có nghĩa là người sản xuất và người tiêu dùng có thể tồn tại hoàn toàn mà không có sự hiện diện của người khác.

Một sự khác biệt không quá tinh tế là nhiều người quan sát trên cùng một quan sát thường có cùng một trọng tải (trừ khi có một triển khai độc đáo), trong khi nhiều người tiêu dùng cùng một nhà sản xuất có thể không. Điều này phụ thuộc nếu trung gian là một cách tiếp cận giống như hàng đợi hoặc giống như chủ đề. Cái trước truyền một thông điệp khác nhau cho mỗi người tiêu dùng, trong khi cái sau đảm bảo (hoặc cố gắng) rằng tất cả người tiêu dùng xử lý trên cơ sở mỗi tin nhắn.

Để phù hợp với chúng vào ứng dụng của bạn:

  • Trong mẫu Observable / Observer, bất cứ khi nào luồng xem của bạn đang khởi tạo, nó phải biết cách thông báo cho bộ điều khiển. Là người quan sát, bộ điều khiển có thể đang chờ thông báo từ luồng xem trước khi nó cho phép các luồng xử lý thay đổi.
  • Trong mẫu Nhà sản xuất / Người tiêu dùng, luồng xem của bạn chỉ cần biết sự hiện diện của hàng đợi sự kiện và chỉ tương tác với điều đó. Là người tiêu dùng, bộ điều khiển sau đó bỏ phiếu hàng đợi sự kiện và một khi nó nhận được một trọng tải mới, nó cho phép các luồng xử lý nó.

Do đó, để trả lời trực tiếp câu hỏi của bạn: nếu bạn muốn duy trì một mức độ tách biệt giữa luồng xem và bộ điều khiển của bạn để bạn có thể vận hành chúng một cách độc lập, bạn nên hướng tới mẫu Nhà sản xuất / Người tiêu dùng.


2
Cảm ơn bạn đã trả lời chi tiết của bạn. Thật không may, tôi không thể nâng cao nó vì thiếu danh tiếng, vì vậy tôi đã đánh dấu nó như một giải pháp thay thế. Sự độc lập tạm thời giữa cả hai phần mà bạn đề cập là điều gì đó tích cực mà tôi chưa từng nghĩ đến cho đến bây giờ. Hàng đợi có thể quản lý các đợt ngắn của nhiều sự kiện với các khoảng dừng dài ở giữa tốt hơn nhiều so với hành động trực tiếp sau khi các sự kiện được quan sát (nếu số lượng luồng tối đa được cố định và tương đối thấp). Số lượng chủ đề cũng có thể được tăng / giảm động tùy thuộc vào số lượng mục hàng hiện tại.
dùng183536

@ user183536 Không có vấn đề gì, rất vui được giúp đỡ! :)
hjk
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.