简体   繁体   English

使用Guava EventBus进行Java多线程处理

[英]Java multithreading with Guava EventBus

I am using guava event bus. 我正在使用番石榴事件总线。 I have a server-like object that is supposed to be running all the time, listening for events to be posted to the b us. 我有一个类似服务器的对象应该一直在运行,监听要发布给b us的事件。 So in a junit test (MyObject is class under test), I create it in its own thread to simulate this and prevent blocking: 所以在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();
      ...
  }

All is good, myObject is created off in its own thread, Thread1. 一切都很好,myObject是在自己的线程Thread1中创建的。 Then later, I post an event to the event bus in my test: 然后,我在测试中将事件发布到事件总线:

eventBus.post(triggerObject);

The weird thing I am finding is that all the actions/logging from my subscribed method inside of MyObject class are executing in the main thread again. 我发现的奇怪的事情是,我在MyObject类中的订阅方法的所有操作/日志记录都在主线程中再次执行。 myObject waits for responses from certain other parts, and this blocks my test since it's in the main thread. myObject等待来自某些其他部分的响应,这会阻止我的测试,因为它在主线程中。 Why is this happening? 为什么会这样? Is it something I am doing wrong with the EventBus or Java threading? 我在EventBus或Java线程上做错了吗?

Well you don't do nothing in the created thread except creating an object which finally ends up in heap (which is shared between threads), but since the reference to it is to not maintained after run, then it's also lost. 好吧,除了创建一个最终在堆中的对象(在线程之间共享)之外,你不会在创建的线程中做任何事情,但由于对它的引用是在运行后没有保持,所以它也会丢失。

Your @Subscribe method from myObject is invoked in the same thread that calls eventBus.post(event); myObject @Subscribe方法在调用eventBus.post(event);的同一个线程中调用eventBus.post(event); and not in the thread that created myObject . 而不是在创建myObject的线程中。

The weird thing I am finding is that all the actions/logging from my subscribed method inside of MyObject class are executing in the main thread again 我发现的奇怪的事情是我在MyObject类中的订阅方法的所有操作/日志记录都在主线程中再次执行

If your MyObject class has an @Subscribe method, then why does it need an instance of EventBus inside the constructor? 如果你的MyObject类有一个@Subscribe方法,为什么它需要构造函数中的EventBus实例? You probably want 你可能想要

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

instead of MyObject myObject = new MyObject(eventBus); 而不是MyObject myObject = new MyObject(eventBus);

It's something you are doing wrong with the EventBus: when you post an event to the EventBus, the handlers for that thread are called in the same thread that does the post. 这是你在EventBus上做错的事情:当你向EventBus发布一个事件时,该线程的处理程序会在发布帖子的同一个线程中调用。

In detail, what's happening under the covers is that EventBus is storing the queue of handlers to execute in a ThreadLocal queue. 详细地说,正在发生的事情是EventBus正在存储处理程序队列以在ThreadLocal队列中执行。 Until a thread needs the queue, it doesn't exist; 在线程需要队列之前,它不存在; when you post the first message, the ThreadLocalMap is initialized with an empty queue which is attached to the running thread. 当您发布第一条消息时,ThreadLocalMap将使用附加到正在运行的线程的空队列进行初始化。 For this reason, the queue of events is drained in the same thread that posts the events. 因此,事件队列在发布事件的同一线程中耗尽。

When multiple threads share an instance of an EventBus , what's shared between them is the registry of event handlers -- the same instance(s) of the subscriber(s) will be called no matter which thread posts the event. 当多个线程共享一个EventBus的实例时,它们之间共享的是事件处理程序的注册表 - 无论哪个线程发布事件,都将调用相同的订阅者实例。 But the subscribers get called on the same thread as the post(). 但是订阅者与post()在同一个线程上被调用。

See Dispatcher.PerThreadQueuedDispatcher -- that code probably doesn't match what you were using in 2014, but at the moment I think it's a lot more comprehensible than trying to find the same functionality in the original implementation. 请参阅Dispatcher.PerThreadQueuedDispatcher - 该代码可能与您在2014年使用的代码不匹配,但目前我认为它比在原始实现中找到相同的功能更容易理解。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM