EventBus原始碼解讀詳細註釋(3)PostThread、MainThread、BackgroundThread、Async四種執行緒模式的區別

王世暉發表於2016-03-20

[EventBus原始碼分析(一):入口函式提綱挈領(2.4版本)](http://blog.csdn.net/wangshihui512/article/details/51802172)
[EventBus原始碼分析(二):register方法儲存事件的訂閱者列表(2.4版本)](http://blog.csdn.net/wangshihui512/article/details/51819508)
[EventBus原始碼分析(三):post方法釋出事件【獲取事件的所有訂閱者,反射呼叫訂閱者事件處理方法】(2.4版本)](http://blog.csdn.net/wangshihui512/article/details/51821143)
[EventBus原始碼分析(四):執行緒模型分析(2.4版本)](http://blog.csdn.net/wangshihui512/article/details/51832001)
[EventBus原始碼解讀詳細註釋(1)register的幕後黑手](http://blog.csdn.net/wangshihui512/article/details/50914817)
[EventBus原始碼解讀詳細註釋(2)MainThread執行緒模型分析](http://blog.csdn.net/wangshihui512/article/details/50934012)
[EventBus原始碼解讀詳細註釋(3)PostThread、MainThread、BackgroundThread、Async四種執行緒模式的區別](http://blog.csdn.net/wangshihui512/article/details/50935729)
[EventBus原始碼解讀詳細註釋(4)register時重新整理的兩個map](http://blog.csdn.net/wangshihui512/article/details/50938663)
[EventBus原始碼解讀詳細註釋(5)事件訊息繼承性分析 eventInheritance含義](http://blog.csdn.net/wangshihui512/article/details/50947102)
[EventBus原始碼解讀詳細註釋(6)從事件釋出到事件處理,究竟發生了什麼!](http://blog.csdn.net/wangshihui512/article/details/50949960)



PostThread:直接在釋出者執行緒呼叫事件處理方法

MainThread:如果釋出者執行緒是主執行緒,那麼直接在釋出者執行緒(主執行緒)裡邊呼叫事件處理方法;如果釋出者執行緒不是主執行緒,就把此事件送到主執行緒訊息迴圈處理佇列,在主執行緒中處理此事件

BackgroundThread:如果釋出者執行緒是主執行緒,那麼把此事件傳送到一個專門處理後臺執行緒的訊息迴圈處理佇列,該佇列管理多個後臺執行緒;如果釋出者不是主執行緒,那麼在釋出者執行緒中直接呼叫事件處理方法

Async:並不使用佇列管理多個事件,也不管釋出者處在主執行緒與否,為每一個事件單獨開闢一個執行緒處理

private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
        switch (subscription.subscriberMethod.threadMode) {
            case PostThread:
                /*在釋出者的執行緒裡邊通過反射執行事件處理方法*/
                invokeSubscriber(subscription, event);
                break;
            case MainThread:
                /*如果釋出者執行緒是主執行緒,直接在主執行緒裡邊通過反射執行事件處理方法*/
                if (isMainThread) {
                    invokeSubscriber(subscription, event);
                    /*如果釋出者執行緒不是主執行緒,就把此事件加入主執行緒訊息迴圈處理佇列,在主執行緒中
                    * 通過反射呼叫事件處理方法*/
                } else {
                    mainThreadPoster.enqueue(subscription, event);
                }
                break;
            case BackgroundThread:
                /*如果釋出者執行緒是主執行緒,那麼就把此事件加入後臺執行緒訊息迴圈處理佇列
                * 通過反射呼叫事件處理方法,此執行緒模式多個事件都在一個後臺執行緒中迴圈處理
                * 通過佇列管理多個事件*/
                if (isMainThread) {
                    backgroundPoster.enqueue(subscription, event);
                } else {
                    /*釋出者不在主執行緒,那麼在釋出者執行緒中直接通過反射呼叫事件處理方法*/
                    invokeSubscriber(subscription, event);
                }
                break;
            case Async:
                /*這種執行緒模式是直接開一個新的執行緒,呼叫事件處理方法,雖然看起來像是
                * 通過佇列在一個後臺執行緒中迴圈管理多個事件,但是通過閱讀原始碼發現並不是這樣,
                * 而是為每一個事件都單獨開闢一個執行緒*/
                asyncPoster.enqueue(subscription, event);
                break;
            default:
                throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
        }
    }


MianThread執行緒模型參看上篇 Event原始碼解讀詳細註釋(2)MainThread執行緒模型分析

BackgroundThread執行緒模型通過佇列管理多個執行緒

final class BackgroundPoster implements Runnable {
    /*訊息佇列*/
    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;
                /*進佇列後判斷此執行緒是否在執行,如果沒有在執行就執行此執行緒(呼叫run方法)*/
                eventBus.getExecutorService().execute(this);
            }
        }
    }
    /*執行緒執行體*/
    @Override
    public void run() {
        try {
            try {
                /*迴圈處理訊息*/
                while (true) {
                    /*訊息佇列隊首出佇列,將被掛起1秒,直到有訊息入佇列或者1秒到時*/
                    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) {
                Log.w("Event", Thread.currentThread().getName() + " was interruppted", e);
            }
        } finally {
            /*設定標誌位,方便新的事件可以賴皮新的執行緒處理*/
            executorRunning = false;
        }
    }

}

Async執行緒模型為每一個事件單獨開闢一個執行緒:

class AsyncPoster implements Runnable {

    private final PendingPostQueue queue;
    private final EventBus eventBus;

    AsyncPoster(EventBus eventBus) {
        this.eventBus = eventBus;
        queue = new PendingPostQueue();
    }

    public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        queue.enqueue(pendingPost);
        /*進佇列後就立即執行此執行緒,為每一個事件單獨開一個執行緒,因此不需要判斷執行緒是否在執行,也不需要迴圈遍歷*/
        eventBus.getExecutorService().execute(this);
    }

    @Override
    public void run() {
         /*為每一個事件單獨開一個執行緒,因此不需要判斷執行緒是否在執行,也不需要迴圈遍歷*/
        PendingPost pendingPost = queue.poll();
        if(pendingPost == null) {
            throw new IllegalStateException("No pending post available");
        }
        /*執行緒執行體裡邊直接通過反射呼叫事件處理方法*/
        eventBus.invokeSubscriber(pendingPost);
    }

}




相關文章