鴻蒙OS 線程間通信開發(fā)指導

2021-08-05 14:31 更新

場景介紹

EventHandler開發(fā)場景

EventHandler 的主要功能是將 InnerEvent 事件或者 Runnable 任務投遞到其他的線程進行處理,其使用的場景包括:

  • 開發(fā)者需要將 InnerEvent 事件投遞到新的線程,按照優(yōu)先級和延時進行處理。投遞時,EventHandler 的優(yōu)先級可在 IMMEDIATE、HIGH、LOW、IDLE 中選擇,并設置合適的 delayTime。
  • 開發(fā)者需要將 Runnable 任務投遞到新的線程,并按照優(yōu)先級和延時進行處理。投遞時, EventHandler 的優(yōu)先級可在 IMMEDIATE、HIGH、LOW、IDLE 中選擇,并設置合適的 delayTime。
  • 開發(fā)者需要在新創(chuàng)建的線程里投遞事件到原線程進行處理。

EventRunner工作模式

EventRunner 的工作模式可以分為托管模式和手動模式。兩種模式是在調用 EventRunner 的 create() 方法時,通過選擇不同的參數來實現的,詳見 API 參考。默認為托管模式。

  • 托管模式:不需要開發(fā)者調用 run() 和 stop() 方法去啟動和停止 EventRunner。當 EventRunner 實例化時,系統(tǒng)調用 run() 來啟動 EventRunner;當 EventRunner 不被引用時,系統(tǒng)調用 stop() 來停止 EventRunner。
  • 手動模式:需要開發(fā)者自行調用 EventRunner 的 run() 方法和 stop() 方法來確保線程的啟動和停止。

接口說明

EventHandler

  • EventHandler 的屬性 Priority (優(yōu)先級)介紹:

EventRunner 將根據優(yōu)先級的高低從事件隊列中獲取事件或者 Runnable 任務進行處理。

屬性 描述
Priority.IMMEDIATE 表示事件被立即投遞
Priority.HIGH 表示事件先于 LOW 優(yōu)先級投遞
Priority.LOW 表示事件優(yōu)于 IDLE 優(yōu)先級投遞,事件的默認優(yōu)先級是 LOW
Priority.IDLE 表示在沒有其他事件的情況下,才投遞該事件

  • EventHandler 的主要接口介紹:
接口名 描述
EventHandler(EventRunner runner) 利用已有的 EventRunner 來創(chuàng)建 EventHandler
current() 在processEvent 回調中,獲取當前的 EventHandler
processEvent(InnerEvent event) 回調處理事件,由開發(fā)者實現
sendEvent(InnerEvent event) 發(fā)送一個事件到事件隊列,延時為 0 ms, 優(yōu)先級為 LOW
sendEvent(InnerEvent event, long delayTime) 發(fā)送一個延時事件到事件隊列,優(yōu)先級為 LOW
sendEvent(InnerEvent event, long delayTime, EventHandler.Priority priority) 發(fā)送一個指定優(yōu)先級的延時事件到事件隊列
sendEvent(InnerEvent event, EventHandler.Priority priority) 發(fā)送一個指定優(yōu)先級的事件到事件隊列,延時為 0 ms
sendSyncEvent(InnerEvent event) 發(fā)送一個同步事件到事件隊列,延時為 0 ms,優(yōu)先級為 LOW
sendSyncEvent(InnerEvent event, EventHandler.Priority priority) 發(fā)送一個指定優(yōu)先級的同步事件到事件隊列,延時為 0 ms,優(yōu)先級不可以是 IDLE
postSyncTask(Runnable task) 發(fā)送一個 Runnable 同步任務到事件隊列,延時為 0 ms, 優(yōu)先級為 LOW
postSyncTask(Runnable task, EventHandler.Priority priority) 發(fā)送一個指定優(yōu)先級的 Runnable 同步任務到事件隊列,延時為 0 ms
postTask(Runnable task) 發(fā)送一個 Runnable 任務到事件隊列,延時為 0 ms,優(yōu)先級為 LOW
postTask(Runnable task, long delayTime) 發(fā)送一個 Runnable 延時任務到事件隊列,優(yōu)先級為 LOW
postTask(Runnable task, long delayTime, EventHandler.Priority priority) 發(fā)送一個指定優(yōu)先級的 Runnable 延時任務到事件隊列
postTask(Runnable task, EventHandler.Priority priority) 發(fā)送一個指定優(yōu)先級的 Runnable 任務到事件隊列,延時為 0 ms
sendTimingEvent(InnerEvent event, long taskTime) 發(fā)送一個定時事件到隊列,在 taskTime 時間執(zhí)行,如果 taskTime 小于當前時間,立即執(zhí)行,優(yōu)先級為 LOW
sendTimingEvent(InnerEvent event, long taskTime, EventHandler.Priority priority) 發(fā)送一個帶優(yōu)先級的事件到隊列,在 taskTime 時間執(zhí)行,如果 taskTime 小于當前時間,立即執(zhí)行
postTimingTask(Runnable task, long taskTime) 發(fā)送一個 Runnable 任務到隊列,在 taskTime 時間執(zhí)行,如果 taskTime 小于當前時間,立即執(zhí)行,優(yōu)先級為 LOW
postTimingTask(Runnable task, long taskTime, EventHandler.Priority priority) 發(fā)送一個帶優(yōu)先級的 Runnable 任務到隊列,在 taskTime 時間執(zhí)行,如果 taskTime 小于當前時間,立即執(zhí)行
removeEvent(int eventId) 刪除指定 id 的事件
removeEvent(int eventId, long param) 刪除指定 id 和 param 的事件
removeEvent(int eventId, long param, Object object) 刪除指定 id、param 和 object 的事件
removeAllEvent() 刪除該EventHandler的所有事件
getEventName(InnerEvent event) 獲取事件的名字
getEventRunner() 獲取該 EventHandler 綁定的 EventRunner
isIdle() 判斷隊列是否為空
hasInnerEvent(Runnable runnable) 是否有還未被處理的這個任務

EventRunner

  • EventRunner的主要接口介紹:
接口名 描述
create() 創(chuàng)建一個擁有新線程的 EventRunner
create(boolean inNewThread) 創(chuàng)建一個擁有新線程的 EventRunner,isDeposited 為 true 時,EventRunner 為托管模式,系統(tǒng)將自動管理該 EventRunner;isDeposited 為 false 時,EventRunner 為手動模式。
create(String newThreadName) 創(chuàng)建一個擁有新線程的 EventRunner, 新線程的名字是 newThreadName
current() 獲取當前線程的 EventRunner
run() EventRunner 為手動模式時,調用該方法啟動新的線程
stop() EventRunner 為手動模式時,調用該方法停止新的線程

InnerEvent

  • InnerEvent的屬性介紹:
屬性 描述
eventId 事件的 ID, 由開發(fā)者定義用來辨別事件
object 事件攜帶的 Object 信息
param 事件攜帶的 long 型數據

  • InnerEvent的主要接口介紹:
接口名 描述
drop() 釋放一個事件實例
get() 獲得一個事件實例
get(int eventId) 獲得一個指定的 eventId 的事件實例
get(int eventId, long param) 獲得一個指定的 eventId 和 param 的事件實例
get(int eventId, long param, Object object) 獲得一個指定的 eventId, param 和 object 的事件實例
get(int eventId, Object object) 獲得一個指定的 eventId 和 object 的事件實例
PacMap getPacMap() 獲取 PacMap,如果沒有,會新建一個
Runnable getTask() 獲取 Runnable 任務
PacMap peekPacMap() 獲取 PacMap
void setPacMap(PacMap pacMap) 設置 PacMap

開發(fā)步驟

EventHandler 投遞 InnerEvent 事件

EventHandler 投遞 InnerEvent 事件,并按照優(yōu)先級和延時進行處理,開發(fā)步驟如下:

  1. 創(chuàng)建 EventHandler 的子類,在子類中重寫實現方法 processEvent() 來處理事件。

   private class MyEventHandler extends EventHandler {
       private MyEventHandler(EventRunner runner) {
       super(runner);
       }
       // 重寫實現processEvent方法
       @Override
       public void processEvent(InnerEvent event) {
       super.processEvent(event);
       if (event == null) {
               return;
       }
       int eventId = event.eventId;
       long param = event.param;
       switch (eventId | param) {
               case CASE1:
                   // 待執(zhí)行的操作,由開發(fā)者定義
               break;
           default:
           break;
       }
       }
   }

  1. 創(chuàng)建 EventRunner,以手動模式為例。

   EventRunner runner = EventRunner.create(false);// create()的參數是 true時,則為托管模式
   // 需要對 EventRunner 的實例進行校驗,因為創(chuàng)建 EventRunner 可能失敗,如創(chuàng)建線程失敗時,創(chuàng)建 EventRunner 失敗。
   if (runner == null) {
       return;
   }

  1. 創(chuàng)建 EventHandler 子類的實例。

   MyEventHandler myHandler = new MyEventHandler(runner);

  1. 獲取 InnerEvent 事件。

   // 獲取事件實例,其屬性 eventId, param, object 由開發(fā)者確定,代碼中只是示例。
   int eventId1 = 0;
   int eventId2 = 1; 
   long param = 0; 
   Object object = null; 
   InnerEvent event1 = InnerEvent.get(eventId1, param, object);
   InnerEvent event2 = InnerEvent.get(eventId2, param, object);

  1. 投遞事件,投遞的優(yōu)先級以 IMMEDIATE 為例,延時選擇 0ms和 2ms。

   // 優(yōu)先級 immediate,投遞之后立即處理,延時為 0ms,該語句等價于同步投遞sendSyncEvent(event1,EventHandler.Priority.immediate);
   myHandler.sendEvent(event1, 0, EventHandler.Priority.IMMEDIATE);
   myHandler.sendEvent(event2, 2, EventHandler.Priority.IMMEDIATE); // 延時 2ms 后立即處理

  1. 啟動和停止 EventRunner,如果為托管模式,則不需要此步驟。

   runner.run();
   //待執(zhí)行操作
   runner.stop();// 開發(fā)者根據業(yè)務需要在適當時機停止 EventRunner

EventHandler 投遞 Runnable 任務

EventHandler 投遞Runnable 任務,并按照優(yōu)先級和延時進行處理,開發(fā)步驟如下:

  1. 創(chuàng)建 EventHandler 的子類,創(chuàng)建 EventRunner,并創(chuàng)建 EventHandler 子類的實例,步驟與[ EventHandler 投遞 InnerEvent] 場景的步驟1-3相同。

  1. 創(chuàng)建 Runnable 任務。

   Runnable task1 = new Runnable() {
       @Override
       public void run() {
           // 待執(zhí)行的操作,由開發(fā)者定義
       }
   };
   Runnable task2 = new Runnable() {
       @Override
       public void run() {
           // 待執(zhí)行的操作,由開發(fā)者定義
       }
   };

  1. 投遞 Runnable 任務,投遞的優(yōu)先級以 IMMEDIATE 為例,延時選擇 0ms 和 2ms。

   //優(yōu)先級為 immediate,延時 0ms,該語句等價于同步投遞myHandler.postSyncTask(task1,EventHandler.Priority.immediate);
   myHandler.postTask(task1,0, EventHandler.Priority.IMMEDIATE);

    
   myHandler.postTask(task2,2, EventHandler.Priority.IMMEDIATE);// 延時2ms后立即執(zhí)行

  1. 啟動和停止 EventRunner,如果是托管模式,則不需要此步驟。

   runner.run();
   //待執(zhí)行操作

    
   runner.stop();// 停止 EventRunner

在新創(chuàng)建的線程里投遞事件到原線程

EventHandler 從新創(chuàng)建的線程投遞事件到原線程并進行處理,開發(fā)步驟如下:

  1. 創(chuàng)建 EventHandler 的子類,在子類中重寫實現方法 processEvent() 來處理事件。

   private class MyEventHandler extends EventHandler {
       private MyEventHandler(EventRunner runner) {
       super(runner);
       }
       // 重寫實現processEvent方法
       @Override
       public void processEvent(InnerEvent event) {
       super.processEvent(event);
       if (event == null) {
               return;
       }
       int eventId = event.eventId;
       long param = event.param;
           Object object = event.object;
       switch (eventId | param) {
               case CASE1:
                   // 待執(zhí)行的操作,由開發(fā)者定義
               break;
               case CASE2:
                   // 將原先線程的EventRunner實例投遞給新創(chuàng)建的線程
                   if (object instanceof EventRunner) {
                   EventRunner runner2 = (EventRunner)object;
                   }
                   // 將原先線程的EventRunner實例與新創(chuàng)建的線程的EventHandler綁定
                   EventHandler myHandler2 = new EventHandler(runner2) {
                   @Override
                   public void processEvent(InnerEvent event) {
                  //需要在原先線程執(zhí)行的操作
                   }
                   };
                   int eventId = 1; 
                   long param = 0; 
                   Object object = null; 
                   InnerEvent event2 = InnerEvent.get(eventId, param, object);
                   myHandler2.sendEvent(event2); // 投遞事件到原先的線程
                   break;
           default:
           break;
       }
       }
   }

  1. 創(chuàng)建 EventRunner,以手動模式為例。

   EventRunner runner1 = EventRunner.create(false);// create()的參數是true時,則為托管模式。
   // 需要對 EventRunner 的實例進行校驗,不是任何線程都可以通過 create 創(chuàng)建,例如:當線程池已滿時,不能再創(chuàng)建線程。
   if (runner1 == null) {
       return;
   }

  1. 創(chuàng)建 EventHandler 子類的實例。

   MyEventHandler myHandler1 = new MyEventHandler(runner1);

  1. 獲取 InnerEvent 事件。

   // 獲取事件實例,其屬性 eventId, param, object 由開發(fā)者確定,代碼中只是示例。
   int eventId1 = 0;
   long param = 0; 
   Object object = (Object) EventRunner.current();
   InnerEvent event1 = InnerEvent.get(eventId1, param, object);

  1. 投遞事件,在新線程上直接處理。

   // 將與當前線程綁定的 EventRunner 投遞到與 runner1 創(chuàng)建的新線程中  myHandler.sendEvent(event1);

  1. 啟動和停止 EventRunner,如果是托管模式,則不需要此步驟。

   runner.run();
   //待執(zhí)行操作

    
   runner.stop();// 停止 EventRunner

完整代碼示例

  • 非托管情況:

  //全局:
  EventRunner runnerA

   
  //線程A:
  runnerA = EventRunner.create(false);
  runnerA.run(); // run之后一直循環(huán)卡在這里,所以需要新建一個線程run

   
  //線程B:
  //1.創(chuàng)建類繼承EventHandler
  public class MyEventHandler extends EventHandler {
      public static int CODE_DOWNLOAD_FILE1;
      public static int CODE_DOWNLOAD_FILE2;
      public static int CODE_DOWNLOAD_FILE3;
      private MyEventHandler(EventRunner runner) {
          super(runner);
      }

   
      @Override
      public void processEvent(InnerEvent event) {
          super.processEvent(event);
          if (event == null) {
              return;
          }

   
          int eventId = event.eventId;
          if (STOP_EVENT_ID != eventId) {
              resultEventIdList.add(eventId);
          }

   
          switch (eventId) {
              case CODE_DOWNLOAD_FILE1: {
                  ... // your process
                  break;
              }
              case CODE_DOWNLOAD_FILE1: {
                  ... // your process
                  break;
              }
              case CODE_DOWNLOAD_FILE1: {
                  ... // your process
                  break;
              }
              default:
                  break;
          }
      }
  }

   
  //2.創(chuàng)建 MyEventHandler 實例
  MyEventHandler handler = new MyEventHandler(runnerA);

   
  // 3.向線程 A 發(fā)送事件
  handler.sendEvent(CODE_DOWNLOAD_FILE1);
  handler.sendEvent(CODE_DOWNLOAD_FILE2);
  handler.sendEvent(CODE_DOWNLOAD_FILE3);
  ......

   
  // 4.runnerA 不再使用后,退出
  runnerA.stop();

  • 托管情況:

  //1.創(chuàng)建 EventRunner A:
  EventRunner runnerA = EventRunner.create("downloadRunner"); // 內部會新建一個線程

   
  //2.創(chuàng)建類繼承 EventHandler
  public class MyEventHandler extends EventHandler {
      public static int CODE_DOWNLOAD_FILE1;
      public static int CODE_DOWNLOAD_FILE2;
      public static int CODE_DOWNLOAD_FILE3;
      private MyEventHandler(EventRunner runner) {
          super(runner);
      }

   
      @Override
      public void processEvent(InnerEvent event) {
          super.processEvent(event);
          if (event == null) {
              return;
          }

   
          int eventId = event.eventId;
          if (STOP_EVENT_ID != eventId) {
              resultEventIdList.add(eventId);
          }

   
          switch (eventId) {
              case CODE_DOWNLOAD_FILE1: {
                  ... // your process
                  break;
              }
              case CODE_DOWNLOAD_FILE1: {
                  ... // your process
                  break;
              }
              case CODE_DOWNLOAD_FILE1: {
                  ... // your process
                  break;
              }
              default:
                  break;
          }
      }
  }

   
  //3.創(chuàng)建MyEventHandler實例
  MyEventHandler handler = new MyEventHandler(runnerA);

   
  //4.向線程A發(fā)送事件
  handler.sendEvent(CODE_DOWNLOAD_FILE1);
  handler.sendEvent(CODE_DOWNLOAD_FILE2);
  handler.sendEvent(CODE_DOWNLOAD_FILE3);
  ......

   
  //5.runnerA沒有任何對象引入時,線程會自動回收
  runnerA = null;
以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號