소비자 / 프로듀서와 관찰자 / 관찰 가능한 차이점


15

세 부분으로 구성된 응용 프로그램 디자인을 연구하고 있습니다.

  • 특정 이벤트 (파일 생성, 외부 요청 등)를 감시하는 단일 스레드
  • 이러한 이벤트를 처리하여 응답하는 N 작업자 스레드 (각 작업자 프로세스 및 단일 이벤트 소비 및 처리에 시간이 걸릴 수 있음)
  • 해당 스레드를 관리하고 오류 처리 (스레드 재시작, 결과 로깅)를 수행하는 컨트롤러

이것은 매우 기본적이고 구현하기 어렵지는 않지만, "올바른"방법이 무엇인지 궁금합니다 (이 구체적인 경우 Java에서는 더 높은 추상화 응답도 감사합니다). 두 가지 전략이 떠 오릅니다.

  • 관찰 / 관찰 가능 : 컨트롤러가 관찰 스레드를 관찰합니다. 이벤트가 발생하면 컨트롤러에 알림이 전달되고 재사용 가능한 캐시 된 스레드 풀에서 사용 가능한 스레드에 새 작업을 할당 할 수 있습니다 (또는 모든 스레드가 현재 사용중인 경우 FIFO 대기열에서 작업을 캐시에 저장). 작업자 스레드는 Callable을 구현하고 결과 (또는 부울 값)와 함께 성공을 반환하거나 오류와 함께 반환합니다.이 경우 컨트롤러는 수행 할 오류의 유형에 따라 수행 할 작업을 결정할 수 있습니다.

  • 생산자 / 소비자 : 감시 스레드는 컨트롤러 (이벤트 큐)와 BlockingQueue를 공유하고 컨트롤러는 모든 작업자 (태스크 큐 및 결과 큐)와 두 개를 공유합니다. 이벤트의 경우 감시 스레드는 이벤트 큐에 작업 개체를 넣습니다. 컨트롤러는 이벤트 대기열에서 새 작업을 가져 와서 검토 한 후 작업 대기열에 넣습니다. 각 작업자는 새 작업을 기다렸다가 작업 대기열 (처음으로 먼저 제공되고 대기열 자체에서 관리)에서 작업을 가져와 소비하여 결과 또는 오류를 결과 대기열에 다시 넣습니다. 마지막으로, 컨트롤러는 결과 대기열에서 결과를 검색하고 오류 발생시 단계를 수행 할 수 있습니다.

두 접근 방식의 최종 결과는 비슷하지만 각각 약간의 차이가 있습니다.

옵저버를 사용하면 스레드를 직접 제어 할 수 있으며 각 작업은 새로 생성 된 특정 작업자에 의해 이루어집니다. 스레드 생성을위한 오버 헤드는 더 높을 수 있지만 캐시 된 스레드 풀 덕분에 그리 많지는 않습니다. 반면, Observer 패턴은 다중이 아닌 단일 Observer로 축소되어 정확히 설계된 것이 아닙니다.

대기열 전략은 확장하기가 더 쉽습니다. 예를 들어 하나 대신 여러 생산자를 추가하는 것이 간단하고 변경이 필요하지 않습니다. 단점은 전혀 작업을 수행하지 않아도 모든 스레드가 무기한으로 실행되며 오류 / 결과 처리가 첫 번째 솔루션처럼 우아하지 않다는 것입니다.

이 상황에서 가장 적합한 접근법은 무엇이며 왜 그런가? 대부분의 예제는 Observer 케이스에서 새로운 값으로 많은 창을 업데이트하거나 여러 소비자 및 생산자와 처리하는 것과 같이 명확한 사례 만 다루기 때문에 온라인 에서이 질문에 대한 답변을 찾기가 어렵다는 것을 알았습니다. 모든 의견을 높이 평가합니다.

답변:


10

당신은 당신 자신의 질문에 대답하는 데 아주 가깝습니다. :)

Observable / Observer 패턴 (뒤집기)에는 세 가지 사항을 명심해야합니다.

  1. 일반적으로 변경 통지, 즉 '페이로드'는 관찰 가능합니다.
  2. 관찰 가능한 것이 존재합니다 .
  3. 관찰자는 기존 관찰 대상 에게 알려야합니다 (또는 관찰 할 대상이 없습니다).

이러한 점들을 결합함으로써, 관찰 가능한 것은 하류 성분, 즉 관찰자가 무엇인지를 관찰자가 알고 있다는 것이다. 데이터 흐름은 본질적으로 관찰 가능한 것에서 관찰됩니다. 관찰자는 관찰하고있는 것에 의해 단순히 '살아서 죽습니다'.

생산자 / 소비자 패턴에서는 매우 다른 상호 작용을 얻습니다.

  1. 일반적으로 페이로드는 생산을 담당하는 생산자와 독립적으로 존재합니다.
  2. 생산자 소비자의 활동 방식과시기를 모릅니다 .
  3. 소비자는 페이로드의 생산자를 알 필요가 없습니다.

데이터 흐름은 이제 생산자와 소비자 사이에서 완전히 단절됩니다. 생산자가 아는 것은 출력이 있다는 것 뿐이며 소비자는 모두 입력이 있다는 것을 알고 있습니다. 중요한 것은 이는 생산자와 소비자가 다른 존재없이 완전히 존재할 수 있다는 것을 의미합니다.

미묘하지 않은 또 다른 차이점은 동일한 옵저버 블의 여러 옵저버 가 일반적으로 동일한 페이로드를 얻는 반면 (전통적인 구현이없는 한) 동일한 프로듀서의 여러 소비자 는 그렇지 않을 수 있다는 것입니다. 중개자가 대기열 또는 주제와 유사한 접근 방식인지 여부에 따라 다릅니다. 전자는 각 소비자에 대해 다른 메시지를 전달하지만 후자는 모든 소비자가 메시지별로 처리하도록 보장합니다.

그것들을 당신의 어플리케이션에 맞추려면 :

  • Observable / Observer 패턴에서 감시 스레드가 초기화 될 때마다 컨트롤러에 알리는 방법을 알아야합니다. 관찰자로서, 컨트롤러는 스레드가 변경을 처리하기 전에 감시 스레드로부터 알림을 기다리고있을 것입니다.
  • 생산자 / 소비자 패턴에서 관찰 스레드는 이벤트 큐의 존재 만 알면되고 그와 만 상호 작용합니다. 그러면 소비자는 컨트롤러가 이벤트 큐를 폴링하고 새 페이로드를 받으면 스레드가 처리하도록합니다.

따라서 질문에 직접 대답하기 위해 : 독립적으로 조작 할 수 있도록 감시 스레드와 컨트롤러 사이의 일정한 간격을 유지하려면 생산자 / 소비자 패턴을 향해야합니다.


2
자세한 답변 감사합니다. 불행히도 평판이 없어서 투표 할 수 없으므로 대신 솔루션으로 표시했습니다. 당신이 언급 한 두 부분 사이의 시간적 독립은 지금까지 생각하지 않은 긍정적 인 것입니다. 큐는 이벤트가 관찰 된 후 (최대 스레드 수가 고정되어 있고 상대적으로 낮은 경우) 직접 조치보다 훨씬 더 긴 일시 정지로 많은 이벤트의 짧은 버스트를 관리 할 수 ​​있습니다. 현재 큐 항목 수에 따라 스레드 수를 동적으로 늘리거나 줄일 수 있습니다.
user183536

@ user183536 문제 없습니다, 기꺼이 도와 드리겠습니다! :)
hjk 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.