2014-01-16 10 views
5

は:同時Observerパターン

ObserverA、ObserverB、ObserverC全てがAbstractObserverから継承します。

私はオブザーバーのリスト作成:

List<AbstractObserver> list = new ArrayList<AbstractObserver>(); 
list.add(new ObserverA()); 
list.add(new ObserverB()); 
list.add(new ObserverC()); 

をそして、次の方法でハンドラのいくつかの種類が「MAIN」のスレッドで実行されます。

public void eat(Food item) { 
    for(AbstractObserver o : list) { 
      o.eatFood(item); 
    } 
} 

public void drink(Coffee cup) { 
    for(AbstractObserver o : list) { 
      o.drinkCoffee(cup); 
    } 
} 

どのように私は私のシステムを設計しますそれぞれの食べ物を食べることができる食べ物と飲み物別の糸でオブザーバーのコーヒーメソッド?具体的には、 "MAIN"スレッドがイベントを受け取ったときに、どのようにObserverA、ObserverB、ObserverCでeatFoodメソッドまたはdrinkCoffeeメソッドを実行するのですか?

現在、各観測者に遅延が発生する可能性があることを順次通知しているため、各AbstractObserverサブクラスインスタンスに対して異なるスレッドを作成したいと考えています。

+0

オブザーバーがここでどのように役割を果たすのか分かりません。彼らが観察する科目は何ですか?また、どのように食べ物に関係しますか?食べ物と飲み物の方法は何ですか? – Philipp

+0

いいえ、私のためではありません。私の見解では、いつ飲食(MAINスレッドメソッド)が呼び出されるのか分かりません。彼らは5分以上離れて呼び出すことができます。 MAINスレッドの食べ物や飲み物のメソッドが呼び出されたときに、個々のAbstractObserverサブクラスインスタンスが同時にdrinkCoffeeまたはeatFoodを実行できるようにしたいだけです。 – sneeze1

+0

並行処理に制限はありますか?例えば、前のo.eatFood()が終了する前に、同じオブジェクトの次のo.eatFood()を呼び出せますか? –

答えて

2

workQueue.shutdown(); 
+0

このメソッドでは、各メソッド(eat、drinkなど)を変更する必要がありますが、少なくとも1つのworkQueue(20ではなく)しか持たず、スレッドはexecutorフレームワークによって管理されます。並行処理を制限する必要がある場合は、FixedThreadPoolを使用するExecutorをスワップアウトするのと同じくらい簡単です。 – JVMATL

+0

私はassyliasの答えも正しいと思いますが、これは最も簡単な解決策のようです。 – sneeze1

2

私はこれでプロではありませんが、おそらくプロデューサー - コンシューマーの設定を使用することができます。ここでは、監視対象のエンティティであるプロデューサが、独自のスレッド内のキューに通知を追加することができます。消費者は、ここではオブザーバが同じキューから取得し、独自のスレッドから取得します。ホバークラフトの答えについては詳しく説明し

2

、あなたの観察者の基本的な実装は次のようになります。

class ObserverA implements Runnable { 
    private final BlockingQueue<Food> queue = new ArrayBlockingQueue<>(); 

    public void eatFood(Food f) { 
     queue.add(f); 
    } 

    public void run() { 
     try { 
      while (true) { 
       Food f = queue.take(); //blocks until some food is on the queue 
       //do what you have to do with that food 
      } 
     } catch (InterruptedException e) { 
      Thread.currentThread().interrupt(); 
      //and exit 
     } 
    } 
} 

のでeatFoodを呼び出すコードは、あなたのメインスレッドをブロックする方法から、すぐに戻っていないでしょう。

オブザーバーにスレッドを割り当てる必要があります。具体的には、直接new Thread(observerA).start();またはExecutorServiceを使用します。これはおそらくより簡単で好ましい方法です。


代わりに、あなたは「観察」オブジェクトレベルでスレッドを作成することができます。

private static final ExecutorService fireObservers = Executors.newFixedThreadPool(10); 

public void eat(Food food) { 
    for (AbstractObserver o : observers) { 
     //(i) if an observer gets stuck, the others can still make progress 
     //(ii) if an observer throws an exception, a new thread will be created 
     Future<?> f = fireObservers.submit(() -> o.dataChanged(food)); 
     fireObservers.submit(new Callable<Void>() { 
      @Override public Void call() throws Exception { 
       try { 
        f.get(1, TimeUnit.SECONDS); 
       } catch (TimeoutException e) { 
        logger.warn("Slow observer {} has not processed food {} in one second", o, food); 
       } catch (ExecutionException e) { 
        logger.error("Observer " + o + " has thrown exception on food " + food, e.getCause()); 
       } 
       return null; 
      } 
     }); 
    } 
} 

(私は主にhereから貼り付けコピーされた - あなたはおそらくあなたのニーズに適合させる必要があります)。への出口で

// declare the work queue 
    private final Executor workQueue = Executors.newCachedThreadPool(); 




    // when you want to eat, schedule a bunch of 'eating' jobs 
     public void eat(final Food item){ 
      for (final AbstractObserver o: list) { 
      workQueue.execute(new Runnable() { 

       @Override 
       public void run() { 
        o.eatFood(item); // runs in background thread 
       } 
      }); 
      } 
     } 

を:あなたはまた、待ち行列に作業をスローするようにエグゼキュータのフレームワークを使用することができ、とき食べる/飲む終了通知取得を気にしないことをここにいくつかの単純化の仮定を作る

+0

ありがとう、私はこれがどのように動作するかを理解していると思います。私の問題は、私はこのルートを行く場合、私はMAINスレッドの各メソッドのために自分自身を作成する必要があります。あなたの例では、私はdrinkFoodのためのメソッドを作成しなければならないと信じています。私のプロジェクトのケースでは、私はこれが必要な約20のメソッドを持っているので、自分自身で20個のキューを処理し、runメソッドでqueue.take()メソッドを処理しようとすると、扱いにくくなるかもしれません。 – sneeze1

+0

@ sneeze1私の編集を参照してください。 – assylias

関連する問題