番石榴中的PerThreadQueuedDispatcher和InstantDispatcher有什么区别?

时间:2018-08-09 03:18:13

标签: java guava

InstantDispatcher的dispatch()方法为:

void dispatch(Object event, Iterator<Subscriber> subscribers) {
  checkNotNull(event);
  while (subscribers.hasNext()) {
    subscribers.next().dispatchEvent(event);
  }
}

它只是将事件调度到每个子级,所以这很容易理解。

但是,PerThreadQueuedDispatcher的相同方法是:

// both queue and dispatching are ThreadLocal.
@Override
void dispatch(Object event, Iterator<Subscriber> subscribers) {
  checkNotNull(event);
  checkNotNull(subscribers);
  Queue<Event> queueForThread = queue.get();
  queueForThread.offer(new Event(event, subscribers)); 
  // Isn't dispatching.get() always return false? Why the if then?
  if (!dispatching.get()) { 
    dispatching.set(true);
    try {
      Event nextEvent;
      while ((nextEvent = queueForThread.poll()) != null) {
        while (nextEvent.subscribers.hasNext()) {
          nextEvent.subscribers.next().dispatchEvent(nextEvent.event);
        }
      }
    } finally {
      dispatching.remove();
      queue.remove();
    }
  }
}

我对这种方法有疑问

  1. 将事件和订阅者封装到一个Event对象中并提供给线程本地队列,然后对其进行轮询以执行与InstantDispatcher.dispatch()相同的逻辑,这有什么意义?
  2. dispatching.get()是否总是返回false?为什么呢?

1 个答案:

答案 0 :(得分:2)

区别在于一个事件触发另一个事件。假设我们有一个事件A触发了事件B和C,而事件B又触发了事件D:

class Test {
    class A {}
    class B {}
    class C {}
    class D {}

    EventBus bus = new EventBus();

    Test() {
        bus.register(this);
        bus.post(new A());
    }

    @Subscribe void listen(A obj) {
        System.out.println("A");
        bus.post(new B());
        bus.post(new C());
    }

    @Subscribe void listen(B obj) {
        System.out.println("B");
        bus.post(new D());
    }

    @Subscribe void listen(C obj) {
        System.out.println("C");
    }

    @Subscribe void listen(D obj) {
        System.out.println("D");
    }
}

我们可以将这些事件想像成一棵树,其中每个事件都产生其他“子”事件:

    A
   / \
  B   C
 /
D

有两种常见的遍历树的方法:深度优先(A,B,D,C)和宽度优先(A,B,C,D)。那是两个调度员之间的区别。

立即调度程序在创建事件时对其进行处理,从而导致深度优先调度。排队的调度程序将事件提交时排队,并通过轮询队列进行处理,从而导致广度优先的调度。 dispatching标志用于将队列处理限制为根事件。子事件将找到设置的标志并继续前进。