EventBus四種執行緒交付模式

TTMMJJ99發表於2017-11-07
EventBus四種執行緒交付模式
原創 2016年11月05日 10:58:02
1、四種模式分別是:POSTING、MAIN、BACKGROUND、ASYNC。如果是想更新UI就使用MAIN模式,如果要進行耗時操作最好是使用ASYNC,因為這個模式能永遠保證在不一樣的執行緒中進行操作,而且都是子執行緒。
(1)POSTING:這種模式就是eventBus預設的模式,我們在使用的時候不需要再訂閱者的方法的註解後面加任何東西(選擇模式),但是這種只能在同一個執行緒中接收,也就是說,如果是在主執行緒中釋出訊息就只能在主執行緒中接收訊息,如果是在子執行緒中,那麼也只能在相同的子執行緒中去接收訊息。如果非要宣告POSTING的話,寫法如下:
@Subscribe(threadMode = ThreadMode.POSTING) public void showMsgFromSecondActivity(MessagePojo msg){ Log.i("test", ((String) msg.obj)); }
(2)MAIN:這種模式保證了訂閱者指定的那個接收方法肯定要主執行緒中執行,可以放心的在裡面執行更新UI操作。無論釋出者是在主執行緒中還是在那一條子執行緒中釋出訊息,這邊接收的都在主執行緒中。寫法如下
@Subscribe(threadMode = ThreadMode.MAIN) public void showMsgFromSecondActivity(MessagePojo msg){ Log.i("test", ((String) msg.obj)); }

(3)BACKGROUND:這種模式無論釋出者是在主執行緒或者是那一條子執行緒中釋出訊息,接收的肯定是在子執行緒中,並且是這樣理解:如果是在主執行緒中釋出訊息,那麼就會隨機開闢一條子執行緒來接收訊息。如果是在子執行緒中釋出訊息,那麼就會在相同的子執行緒來接收訊息。寫法如下:
@Subscribe(threadMode = ThreadMode.BACKGROUDN) public void showMsgFromSecondActivity(MessagePojo msg){ Log.i("test", ((String) msg.obj)); }

(4)ASYNC:這種模式是無論你在那個執行緒中釋出訊息都會在不同的執行緒中接受訊息。如果你在主執行緒中釋出訊息,就會隨機的開闢一條子執行緒來接收訊息;如果是在子執行緒中釋出訊息,就會開闢一條不同的子執行緒來接收訊息。
寫法如下:
@Subscribe(threadMode = ThreadMode.ASYNC) public void showMsgFromSecondActivity(MessagePojo msg){ Log.i("test", ((String) msg.obj)); }
PostThread:直接在釋出者執行緒呼叫事件處理方法
MainThread:如果釋出者執行緒是主執行緒,那麼直接在釋出者執行緒(主執行緒)裡邊呼叫事件處理方法;如果釋出者執行緒不是主執行緒,就把此事件送到主執行緒訊息迴圈處理佇列,在主執行緒
中處理此事件
BackgroundThread:如果釋出者執行緒是主執行緒,那麼把此事件傳送到一個專門處理後臺執行緒的訊息迴圈處理佇列,該佇列管理多個後臺執行緒;如果釋出者不是主執行緒,那麼在釋出者執行緒中直接呼叫事件處理方法
Async:並不使用佇列管理多個事件,也不管釋出者處在主執行緒與否,為每一個事件單獨開闢一個執行緒處理
  1. private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {  
  2.         switch (subscription.subscriberMethod.threadMode) {  
  3.             case PostThread:  
  4.                 /*在釋出者的執行緒裡邊通過反射執行事件處理方法*/  
  5.                 invokeSubscriber(subscription, event);  
  6.                 break;  
  7.             case MainThread:  
  8.                 /*如果釋出者執行緒是主執行緒,直接在主執行緒裡邊通過反射執行事件處理方法*/  
  9.                 if (isMainThread) {  
  10.                     invokeSubscriber(subscription, event);  
  11.                     /*如果釋出者執行緒不是主執行緒,就把此事件加入主執行緒訊息迴圈處理佇列,在主執行緒中 
  12.                     * 通過反射呼叫事件處理方法*/  
  13.                 } else {  
  14.                     mainThreadPoster.enqueue(subscription, event);  
  15.                 }  
  16.                 break;  
  17.             case BackgroundThread:  
  18.                 /*如果釋出者執行緒是主執行緒,那麼就把此事件加入後臺執行緒訊息迴圈處理佇列 
  19.                 * 通過反射呼叫事件處理方法,此執行緒模式多個事件都在一個後臺執行緒中迴圈處理 
  20.                 * 通過佇列管理多個事件*/  
  21.                 if (isMainThread) {  
  22.                     backgroundPoster.enqueue(subscription, event);  
  23.                 } else {  
  24.                     /*釋出者不在主執行緒,那麼在釋出者執行緒中直接通過反射呼叫事件處理方法*/  
  25.                     invokeSubscriber(subscription, event);  
  26.                 }  
  27.                 break;  
  28.             case Async:  
  29.                 /*這種執行緒模式是直接開一個新的執行緒,呼叫事件處理方法,雖然看起來像是 
  30.                 * 通過佇列在一個後臺執行緒中迴圈管理多個事件,但是通過閱讀原始碼發現並不是這樣, 
  31.                 * 而是為每一個事件都單獨開闢一個執行緒*/  
  32.                 asyncPoster.enqueue(subscription, event);  
  33.                 break;  
  34.             default:  
  35.                 throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);  
  36.         }  
  37.     }  


BackgroundThread執行緒模型通過佇列管理多個執行緒
  1. final class BackgroundPoster implements Runnable {  
  2.     /*訊息佇列*/  
  3.     private final PendingPostQueue queue;  
  4.     private final EventBus eventBus;  
  5.     /*標誌位,是否正在執行事件處理方法,防止重複執行*/  
  6.     private volatile boolean executorRunning;  
  7.   
  8.     BackgroundPoster(EventBus eventBus) {  
  9.         this.eventBus = eventBus;  
  10.         queue = new PendingPostQueue();  
  11.     }  
  12.     /*訂閱者和訊息封裝後進佇列*/  
  13.     public void enqueue(Subscription subscription, Object event) {  
  14.         PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);  
  15.         synchronized (this) {  
  16.             queue.enqueue(pendingPost);  
  17.             if (!executorRunning) {  
  18.                 executorRunning = true;  
  19.                 /*進佇列後判斷此執行緒是否在執行,如果沒有在執行就執行此執行緒(呼叫run方法)*/  
  20.                 eventBus.getExecutorService().execute(this);  
  21.             }  
  22.         }  
  23.     }  
  24.     /*執行緒執行體*/  
  25.     @Override  
  26.     public void run() {  
  27.         try {  
  28.             try {  
  29.                 /*迴圈處理訊息*/  
  30.                 while (true) {  
  31.                     /*訊息佇列隊首出佇列,將被掛起1秒,直到有訊息入佇列或者1秒到時*/  
  32.                     PendingPost pendingPost = queue.poll(1000);  
  33.                     /*佇列為空*/  
  34.                     if (pendingPost == null) {  
  35.                         synchronized (this) {  
  36.                             // Check again, this time in synchronized  
  37.                             pendingPost = queue.poll();  
  38.                             /*雙重檢查,佇列確實為空,設定標誌位,直接退出迴圈*/  
  39.                             if (pendingPost == null) {  
  40.                                 executorRunning = false;  
  41.                                 return;  
  42.                             }  
  43.                         }  
  44.                     }  
  45.                     /*訊息佇列隊首不為空,取出來後通過反射呼叫事件處理方法*/  
  46.                     eventBus.invokeSubscriber(pendingPost);  
  47.                 }  
  48.             } catch (InterruptedException e) {  
  49.                 Log.w("Event", Thread.currentThread().getName() + " was interruppted", e);  
  50.             }  
  51.         } finally {  
  52.             /*設定標誌位,方便新的事件可以賴皮新的執行緒處理*/  
  53.             executorRunning = false;  
  54.         }  
  55.     }  
  56.   
  57. }  

Async執行緒模型為每一個事件單獨開闢一個執行緒:
  1. class AsyncPoster implements Runnable {  
  2.   
  3.     private final PendingPostQueue queue;  
  4.     private final EventBus eventBus;  
  5.   
  6.     AsyncPoster(EventBus eventBus) {  
  7.         this.eventBus = eventBus;  
  8.         queue = new PendingPostQueue();  
  9.     }  
  10.   
  11.     public void enqueue(Subscription subscription, Object event) {  
  12.         PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);  
  13.         queue.enqueue(pendingPost);  
  14.         /*進佇列後就立即執行此執行緒,為每一個事件單獨開一個執行緒,因此不需要判斷執行緒是否在執行,也不需要迴圈遍歷*/  
  15.         eventBus.getExecutorService().execute(this);  
  16.     }  
  17.   
  18.     @Override  
  19.     public void run() {  
  20.          /*為每一個事件單獨開一個執行緒,因此不需要判斷執行緒是否在執行,也不需要迴圈遍歷*/  
  21.         PendingPost pendingPost = queue.poll();  
  22.         if(pendingPost == null) {  
  23.             throw new IllegalStateException("No pending post available");  
  24.         }  
  25.         /*執行緒執行體裡邊直接通過反射呼叫事件處理方法*/  
  26.         eventBus.invokeSubscriber(pendingPost);  
  27.     }  
  28.   

相關文章