6

グアバイベントバスを使用しています。私は、イベントがバスに投稿されるのをリッスンして、常に実行されているはずのサーバーのようなオブジェクトを持っています。したがって、junit テスト (MyObject はテスト対象のクラス) で、独自のスレッドで作成して、これをシミュレートし、ブロックを防止します。

  @Test    
  public void test() {
      EventBus eventBus = new EventBus();

      Thread thread= new Thread() {
         @Override
         public void run()
         {
            logger.debug("Creating new thread");
            MyObject myObject = new MyObject(eventBus);
         }
      };

      thread.start();
      ...
  }

すべて問題ありません。myObject は独自のスレッド Thread1 で作成されます。その後、テストでイベント バスにイベントを投稿します。

eventBus.post(triggerObject);

私が見つけた奇妙なことは、 MyObject クラス内のサブスクライブされたメソッドからのすべてのアクション/ロギングがメインスレッドで再び実行されていることです。myObject は特定の他の部分からの応答を待ちます。これは、メイン スレッドにあるため、テストをブロックします。なぜこうなった?EventBus または Java スレッド化で何か間違っているのでしょうか?

4

2 に答える 2

7

作成されたスレッドでは、最終的にヒープ (スレッド間で共有される) になるオブジェクトを作成する以外は何もしませんが、それへの参照は実行後に維持されないため、それも失われます。

@Subscribeからのメソッドは、を作成したスレッドではなく、myObject呼び出すのと同じスレッドで呼び出されます。eventBus.post(event);myObject

私が見つけた奇妙なことは、 MyObject クラス内のサブスクライブされたメソッドからのすべてのアクション/ロギングがメインスレッドで再び実行されていることです

MyObjectクラスにメソッドがある場合@Subscribe、コンストラクター内に EventBus のインスタンスが必要なのはなぜですか? あなたはおそらくしたいです

MyObject myObject = new MyObject();
eventBus.register(myObject);`

それ以外のMyObject myObject = new MyObject(eventBus);

于 2014-08-18T20:41:11.830 に答える
4

これは、EventBus で間違っていることです。イベントを EventBus に投稿すると、そのスレッドのハンドラーが、投稿を行う同じスレッドで呼び出されます。

詳細に言えば、裏で行われていることは、EventBus が実行するハンドラーのキューをキューに格納しているということですThreadLocal。スレッドがキューを必要とするまで、キューは存在しません。最初のメッセージを投稿すると、実行中のスレッドにアタッチされた空のキューで ThreadLocalMap が初期化されます。このため、イベントのキューは、イベントをポストするスレッドと同じスレッドで排出されます。

複数のスレッドが のインスタンスを共有する場合、EventBusそれらの間で共有されるのはイベント ハンドラーのレジストリです。どのスレッドがイベントをポストしても、サブスクライバーの同じインスタンスが呼び出されます。ただし、サブスクライバーは post() と同じスレッドで呼び出されます。

Dispatcher.PerThreadQueuedDispatcherを参照してください。そのコードは、2014 年に使用していたものとおそらく一致しませんが、現時点では、元の実装で同じ機能を見つけようとするよりもはるかに理解しやすいと思います。

于 2015-08-17T21:43:00.120 に答える