源码如下:
final class BackgroundPoster implements Runnable, Poster {
private final PendingPostQueue queue;
private final EventBus eventBus;
private volatile boolean executorRunning;
BackgroundPoster(EventBus eventBus) {
this.eventBus = eventBus;
queue = new PendingPostQueue();
}
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
queue.enqueue(pendingPost);
if (!executorRunning) {
executorRunning = true;
eventBus.getExecutorService().execute(this);
}
}
}
@Override
public void run() {
try {
try {
while (true) {
PendingPost pendingPost = queue.poll(1000);
if (pendingPost == null) {
synchronized (this) {
// Check again, this time in synchronized
pendingPost = queue.poll();
if (pendingPost == null) {
executorRunning = false;
return;
}
}
}
eventBus.invokeSubscriber(pendingPost);
}
} catch (InterruptedException e) {
eventBus.getLogger().log(Level.WARNING, Thread.currentThread().getName() + " was interruppted", e);
}
} finally {
executorRunning = false;
}
}
从源码我得知BackgroundPoster
从线程池中抽取了一个单独线程,循环读取队列中的PendingPost
执行。那么但是既然是单线程,run()
方法中的加锁的目的在哪里呢?我感觉完全可以去除加锁代码,简写成如下的代码:
public void run() {
try {
try {
while (true) {
PendingPost pendingPost = queue.poll(1000);
if (pendingPost == null) {
executorRunning = false;
return;
}
}
eventBus.invokeSubscriber(pendingPost);
}
} catch (InterruptedException e) {
eventBus.getLogger().log(Level.WARNING, Thread.currentThread().getName() + " was interruppted", e);
}
} finally {
executorRunning = false;
}
}
我是在哪方面没有考虑到呢?
1
shily 2019-08-05 10:08:11 +08:00 via Android
enqueue 方法是其他线程调用的啊,大兄弟。
|
2
ChenFanlin 2019-08-05 10:49:21 +08:00 1
EventBusBuilder#DEFAULT_EXECUTOR_SERVICE 是 Executors.newCachedThreadPool();
然后这个 BackgroundPoster 是加了个变量`executorRunning`来使他同时只在一个线程中运行,两个锁是确保`executorRunning`的值不出错,两个加锁的代码块同时只能执行一个 假如去掉了下面一个, 假设一种情况, 如果队列里是空的, 先执行`pendingPost = queue.poll();` 取到 null, **executorRunning 还未赋值为 false 的时候** , 这时候`queue.enqueue()`进去了, ```java if (!executorRunning) { executorRunning = true; eventBus.getExecutorService().execute(this); } ``` 这段代码就不会执行, 就得被推迟到下一次 background 的分发了 **一只小菜鸡, 请轻喷** |
3
ChenFanlin 2019-08-05 10:53:56 +08:00
|
4
maninfog OP @ChenFanlin #3 自己研究了下加上你的解释明白啦 感谢
|