【问题标题】:Java multithreading with Guava EventBus使用 Guava EventBus 的 Java 多线程
【发布时间】:2014-08-18 20:23:33
【问题描述】:

我正在使用番石榴事件总线。我有一个类似服务器的对象,它应该一直在运行,监听要发布到总线的事件。所以在一个 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 线程是不是我做错了什么?

【问题讨论】:

    标签: java multithreading guava event-bus


    【解决方案1】:

    好吧,除了创建一个最终在堆中结束的对象(在线程之间共享)之外,您在创建的线程中什么都不做,但是由于对它的引用在运行后不维护,所以它也丢失了。

    myObject 中的 @Subscribe 方法在调用 eventBus.post(event); 的同一线程中调用,而不是在创建 myObject 的线程中调用。

    我发现奇怪的是,MyObject 类中我订阅的方法中的所有操作/日志记录都再次在主线程中执行

    如果您的MyObject 类有一个@Subscribe 方法,那么为什么它需要在构造函数中创建一个EventBus 实例?你可能想要

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

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

    【讨论】:

    • 我在 MyObject 类中注册。所以在构造函数中,我做了类似的事情:eventBus.register(this);。有什么问题吗?
    • 这是一种“代码气味”,将this 传递给构造函数内的另一个对象。从技术上讲,您将对象 (myObject) 赠送给另一个对象 (eventBus),而您的初始对象尚未完全初始化。更多详情请看这里:ibm.com/developerworks/java/library/j-jtp0618/index.html#2
    【解决方案2】:

    这是您使用 EventBus 做错的事情:当您将事件发布到 EventBus 时,该线程的处理程序会在执行发布的同一线程中调用。

    详细地说,在幕后发生的事情是 EventBus 将要执行的处理程序队列存储在 ThreadLocal 队列中。在线程需要队列之前,它是不存在的;当您发布第一条消息时,ThreadLocalMap 会使用一个空队列初始化,该队列附加到正在运行的线程。因此,事件队列会在发布事件的同一线程中耗尽。

    当多个线程共享EventBus 的实例时,它们之间共享的是事件处理程序的注册表——无论哪个线程发布事件,都将调用订阅者的相同实例。但是订阅者会在与 post() 相同的线程上被调用。

    请参阅Dispatcher.PerThreadQueuedDispatcher——该代码可能与您在 2014 年使用的不匹配,但目前我认为它比尝试在原始实现中找到相同的功能更容易理解。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多