2011-12-17 6 views
4

私は以下の問題があります。 ObserverパターンのためのインタフェースEventNotifier考える:Java:オブザーバーパターンが新しいスレッドで通知される

public interface EventNotifier { 
    void newEvent(final String value); 
} 

このインタフェースを実装するクラス、メソッドNEWEVENT非常に頻繁にを呼び出して別のクラス、で登録することができます。インタフェースは外部ライブラリによって与えられているので、変更することはできません。今まで私は匿名クラスでそれを実装:より良いコードの読みやすさのために

Thread t = new Thread(new Runnable() { 

    @Override  
    public void run() { 

     watcher = new Watcher(new EventNotifier() { 

      @Override 
      public void newEvent(String value) { 
       //do some stuff 
       //will be called more than 20 times per second 
      } 
     }); 
}); 
t.start(); 

を(取り扱いが他のものに平行でなければならないので)私はスレッドを拡張する新しいクラス、にこの匿名クラスを公開したいと思います。

スレッドを作成するにはどうすればよいですか(無限ループはありません)、newEventメソッドの呼び出しを待っていますか?問題は、newEventは1秒間に20回以上呼び出されるため、呼び出しごとに新しいスレッドを開始することはできませんが、すべてがスレッド内になければなりません。

あなたが問題を抱えて誰かが私を助けてくれることを願っています。

+0

現在のデザインでは、リスナーを登録して終了するスレッドがあります。これはあなたが望むものではないと思いますか?別のスレッドで処理するためにnewEventへの呼び出しをしたいですか?これは、他のコンポーネントを実行するスレッドで処理されるためです。 –

答えて

6

投稿が紛らわしいのは、EventNotifierが実際にはオブザーバー/リスナー(イベントを受信して​​も発射しない)であり、Watcherは実際には通知機能です(イベントを作成するウォッチャーですnewEventメソッドを呼び出します)。

私は今からの観測可能なのオブザーバを使用します。 observableはイベントを発生させ、オブザーバのnewEventメソッドを呼び出します。

別のスレッドでイベント処理を実行する場合は、BlockingQueueを使用します。無限にループするスレッドを開始し、各反復でキューからtake()を試行します。 observableにobserverを登録します。observableは受信したイベントを単に受け取り、put()をブロッキングキューに入れます。

1

使用wait/notifyAll、昔ながらのを:Javaのマルチスレッドプログラミングの一般的な概要については

// we need final object to synchronize your code and library code on it 
// it's convenient to make this object hold all needed data to be passed from library as well 
// in your case AtomicBoolean should suffice (we can't use simple `final Boolean`, since it would be impossible to assign new value to it, as we need in code below). 

final AtomicBoolean called = new AtomicBoolean(false); 

EventNotifier en = new EventNotifier() { 
      @Override 
      public void newEvent(String value) { 
       // this will be called by your external library 
       synchronized(called) { 
        called.set(true); called.notifyAll(); 
       } 
      } 
     }; 

Thread t = new Thread(new Runnable() { 
    @Override  
    public void run() { 
     synchronized(called) { 
      // wait here until library call occurs 
      while (!called.get()) { 
       try { 
        called.wait(); 
       } catch (InterruptedException e) { 
        // handle exception as desired 
       } 
      } 
      // reset called flag asap, so we will know when next call occurs 
      called.set(false); 
      ... // do your stuff 
     } 
    ); 
}); 
t.start(); 

は、tutorialをお読みください。興味のあるトピックがある場合は、Goetzの "Java Concurrency in Practice"を読んでください。場合は、あなたはライブラリからnewEventに渡さvalueを処理する必要が

、あなたの代わりに、単純なBooleanBlockingQueueのいくつかの種類が必要になります。

+0

'final Boolean'フラグを変更することはできますか? –

+0

@DarthBelegありがとう、私はそれを修正しました –

2

を使用すると、コードBlockingQueueのコード化を回避し、手作業でスレッドをポーリングすることができます。あなたのメインクラスで

次のようなものがあります:「私はここにEventNotifierを実装しましたが、それはにISN

class ConcurrentEventHandler implements EventNotifier, Runnable { 
     private final String value; 

     public ConcurrentEventHandler(String value) { 
      this.value = value; 
     } 

     public void newEvent(final String value) { 
      // do some stuff 
     } 

     public void run() { 
      // executed in background thread 
      newEvent(value); 
     } 
    } 

Executor eventExecutor = Executors.newSingleThreadExecutor(); 
// ... 
watcher = new Watcher(new EventNotifier() { 
    public void newEvent(final String value) { 
     eventExecutor.execute(new ConcurrentEventHandler(value)); 
    } 
}); 

、バックグラウンドスレッドでの取り扱い行い、同時イベントハンドラをもちろん必要です

関連する問題