树叶云鸿蒙OS教程:鸿蒙OS 线程间通信开发指导

场景介绍

EventHandler开发场景

EventHandler 的主要功能是将 InnerEvent 事件或者 Runnable 任务投递到其他的线程进行处理,其使用的场景包括:

  • 开发者需要将 InnerEvent 事件投递到新的线程,按照优先级和延时进行处理。投递时,EventHandler 的优先级可在 IMMEDIATE、HIGH、LOW、IDLE 中选择,并设置合适的 delayTime。
  • 开发者需要将 Runnable 任务投递到新的线程,并按照优先级和延时进行处理。投递时, EventHandler 的优先级可在 IMMEDIATE、HIGH、LOW、IDLE 中选择,并设置合适的 delayTime。
  • 开发者需要在新创建的线程里投递事件到原线程进行处理。

EventRunner工作模式

EventRunner 的工作模式可以分为托管模式和手动模式。两种模式是在调用 EventRunner 的 create() 方法时,通过选择不同的参数来实现的,详见 API 参考。默认为托管模式。

  • 托管模式:不需要开发者调用 run() 和 stop() 方法去启动和停止 EventRunner。当 EventRunner 实例化时,系统调用 run() 来启动 EventRunner;当 EventRunner 不被引用时,系统调用 stop() 来停止 EventRunner。
  • 手动模式:需要开发者自行调用 EventRunner 的 run() 方法和 stop() 方法来确保线程的启动和停止。

接口说明

EventHandler

  • EventHandler 的属性 Priority (优先级)介绍:

EventRunner 将根据优先级的高低从事件队列中获取事件或者 Runnable 任务进行处理。

属性描述
Priority.IMMEDIATE表示事件被立即投递
Priority.HIGH表示事件先于 LOW 优先级投递
Priority.LOW表示事件优于 IDLE 优先级投递,事件的默认优先级是 LOW
Priority.IDLE表示在没有其他事件的情况下,才投递该事件
  • EventHandler 的主要接口介绍:
接口名描述
EventHandler(EventRunner runner)利用已有的 EventRunner 来创建 EventHandler
current()在processEvent 回调中,获取当前的 EventHandler
processEvent(InnerEvent event)回调处理事件,由开发者实现
sendEvent(InnerEvent event)发送一个事件到事件队列,延时为 0 ms, 优先级为 LOW
sendEvent(InnerEvent event, long delayTime)发送一个延时事件到事件队列,优先级为 LOW
sendEvent(InnerEvent event, long delayTime, EventHandler.Priority priority)发送一个指定优先级的延时事件到事件队列
sendEvent(InnerEvent event, EventHandler.Priority priority)发送一个指定优先级的事件到事件队列,延时为 0 ms
sendSyncEvent(InnerEvent event)发送一个同步事件到事件队列,延时为 0 ms,优先级为 LOW
sendSyncEvent(InnerEvent event, EventHandler.Priority priority)发送一个指定优先级的同步事件到事件队列,延时为 0 ms,优先级不可以是 IDLE
postSyncTask(Runnable task)发送一个 Runnable 同步任务到事件队列,延时为 0 ms, 优先级为 LOW
postSyncTask(Runnable task, EventHandler.Priority priority)发送一个指定优先级的 Runnable 同步任务到事件队列,延时为 0 ms
postTask(Runnable task)发送一个 Runnable 任务到事件队列,延时为 0 ms,优先级为 LOW
postTask(Runnable task, long delayTime)发送一个 Runnable 延时任务到事件队列,优先级为 LOW
postTask(Runnable task, long delayTime, EventHandler.Priority priority)发送一个指定优先级的 Runnable 延时任务到事件队列
postTask(Runnable task, EventHandler.Priority priority)发送一个指定优先级的 Runnable 任务到事件队列,延时为 0 ms
sendTimingEvent(InnerEvent event, long taskTime)发送一个定时事件到队列,在 taskTime 时间执行,如果 taskTime 小于当前时间,立即执行,优先级为 LOW
sendTimingEvent(InnerEvent event, long taskTime, EventHandler.Priority priority)发送一个带优先级的事件到队列,在 taskTime 时间执行,如果 taskTime 小于当前时间,立即执行
postTimingTask(Runnable task, long taskTime)发送一个 Runnable 任务到队列,在 taskTime 时间执行,如果 taskTime 小于当前时间,立即执行,优先级为 LOW
postTimingTask(Runnable task, long taskTime, EventHandler.Priority priority)发送一个带优先级的 Runnable 任务到队列,在 taskTime 时间执行,如果 taskTime 小于当前时间,立即执行
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()创建一个拥有新线程的 EventRunner
create(boolean inNewThread)创建一个拥有新线程的 EventRunner,isDeposited 为 true 时,EventRunner 为托管模式,系统将自动管理该 EventRunner;isDeposited 为 false 时,EventRunner 为手动模式。
create(String newThreadName)创建一个拥有新线程的 EventRunner, 新线程的名字是 newThreadName
current()获取当前线程的 EventRunner
run()EventRunner 为手动模式时,调用该方法启动新的线程
stop()EventRunner 为手动模式时,调用该方法停止新的线程

InnerEvent

  • InnerEvent的属性介绍:
属性描述
eventId事件的 ID, 由开发者定义用来辨别事件
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

开发步骤

EventHandler 投递 InnerEvent 事件

EventHandler 投递 InnerEvent 事件,并按照优先级和延时进行处理,开发步骤如下:

  1. 创建 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:
                   // 待执行的操作,由开发者定义
               break;
           default:
           break;
       }
       }
   }

  1. 创建 EventRunner,以手动模式为例。
   EventRunner runner = EventRunner.create(false);// create()的参数是 true时,则为托管模式
   // 需要对 EventRunner 的实例进行校验,因为创建 EventRunner 可能失败,如创建线程失败时,创建 EventRunner 失败。
   if (runner == null) {
       return;
   }

  1. 创建 EventHandler 子类的实例。
   MyEventHandler myHandler = new MyEventHandler(runner);

  1. 获取 InnerEvent 事件。
   // 获取事件实例,其属性 eventId, param, object 由开发者确定,代码中只是示例。
   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. 投递事件,投递的优先级以 IMMEDIATE 为例,延时选择 0ms和 2ms。
   // 优先级 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();
   //待执行操作
   runner.stop();// 开发者根据业务需要在适当时机停止 EventRunner

EventHandler 投递 Runnable 任务

EventHandler 投递Runnable 任务,并按照优先级和延时进行处理,开发步骤如下:

  1. 创建 EventHandler 的子类,创建 EventRunner,并创建 EventHandler 子类的实例,步骤与[ EventHandler 投递 InnerEvent] 场景的步骤1-3相同。
  1. 创建 Runnable 任务。
   Runnable task1 = new Runnable() {
       @Override
       public void run() {
           // 待执行的操作,由开发者定义
       }
   };
   Runnable task2 = new Runnable() {
       @Override
       public void run() {
           // 待执行的操作,由开发者定义
       }
   };

  1. 投递 Runnable 任务,投递的优先级以 IMMEDIATE 为例,延时选择 0ms 和 2ms。
   //优先级为 immediate,延时 0ms,该语句等价于同步投递myHandler.postSyncTask(task1,EventHandler.Priority.immediate);
   myHandler.postTask(task1,0, EventHandler.Priority.IMMEDIATE);

    
   myHandler.postTask(task2,2, EventHandler.Priority.IMMEDIATE);// 延时2ms后立即执行

  1. 启动和停止 EventRunner,如果是托管模式,则不需要此步骤。
   runner.run();
   //待执行操作

    
   runner.stop();// 停止 EventRunner

在新创建的线程里投递事件到原线程

EventHandler 从新创建的线程投递事件到原线程并进行处理,开发步骤如下:

  1. 创建 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:
                   // 待执行的操作,由开发者定义
               break;
               case CASE2:
                   // 将原先线程的EventRunner实例投递给新创建的线程
                   if (object instanceof EventRunner) {
                   EventRunner runner2 = (EventRunner)object;
                   }
                   // 将原先线程的EventRunner实例与新创建的线程的EventHandler绑定
                   EventHandler myHandler2 = new EventHandler(runner2) {
                   @Override
                   public void processEvent(InnerEvent event) {
                  //需要在原先线程执行的操作
                   }
                   };
                   int eventId = 1; 
                   long param = 0; 
                   Object object = null; 
                   InnerEvent event2 = InnerEvent.get(eventId, param, object);
                   myHandler2.sendEvent(event2); // 投递事件到原先的线程
                   break;
           default:
           break;
       }
       }
   }

  1. 创建 EventRunner,以手动模式为例。
   EventRunner runner1 = EventRunner.create(false);// create()的参数是true时,则为托管模式。
   // 需要对 EventRunner 的实例进行校验,不是任何线程都可以通过 create 创建,例如:当线程池已满时,不能再创建线程。
   if (runner1 == null) {
       return;
   }

  1. 创建 EventHandler 子类的实例。
   MyEventHandler myHandler1 = new MyEventHandler(runner1);

  1. 获取 InnerEvent 事件。
   // 获取事件实例,其属性 eventId, param, object 由开发者确定,代码中只是示例。
   int eventId1 = 0;
   long param = 0; 
   Object object = (Object) EventRunner.current();
   InnerEvent event1 = InnerEvent.get(eventId1, param, object);

  1. 投递事件,在新线程上直接处理。
   // 将与当前线程绑定的 EventRunner 投递到与 runner1 创建的新线程中  myHandler.sendEvent(event1);

  1. 启动和停止 EventRunner,如果是托管模式,则不需要此步骤。
   runner.run();
   //待执行操作

    
   runner.stop();// 停止 EventRunner

完整代码示例

  • 非托管情况:
  //全局:
  EventRunner runnerA

   
  //线程A:
  runnerA = EventRunner.create(false);
  runnerA.run(); // run之后一直循环卡在这里,所以需要新建一个线程run

   
  //线程B:
  //1.创建类继承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.创建 MyEventHandler 实例
  MyEventHandler handler = new MyEventHandler(runnerA);

   
  // 3.向线程 A 发送事件
  handler.sendEvent(CODE_DOWNLOAD_FILE1);
  handler.sendEvent(CODE_DOWNLOAD_FILE2);
  handler.sendEvent(CODE_DOWNLOAD_FILE3);
  ......

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

  • 托管情况:
  //1.创建 EventRunner A:
  EventRunner runnerA = EventRunner.create("downloadRunner"); // 内部会新建一个线程

   
  //2.创建类继承 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.创建MyEventHandler实例
  MyEventHandler handler = new MyEventHandler(runnerA);

   
  //4.向线程A发送事件
  handler.sendEvent(CODE_DOWNLOAD_FILE1);
  handler.sendEvent(CODE_DOWNLOAD_FILE2);
  handler.sendEvent(CODE_DOWNLOAD_FILE3);
  ......

   
  //5.runnerA没有任何对象引入时,线程会自动回收
  runnerA = null;

文章来源网络,作者:管理,如若转载,请注明出处:https://shuyeidc.com/wp/205946.html<

(0)
管理的头像管理
上一篇2025-04-07 20:40
下一篇 2025-04-07 20:42

相关推荐

  • 站群服务器和普通服务器到底哪个更适合GEO,怎么选?

    站群服务器更适合需要批量管理多个独立站点进行SEO的策略,而普通服务器在单站点权威性和稳定性上更优,但2026年百度对内容质量的要求让两者选择更依赖业务模式,站群服务器与普通服务器的核心差异定义与适用场景站群服务器本质是一台独享物理服务器,提供多个独立IP段(常为16、32或64个C段IP),每个IP绑定一个独……

    2026-07-28
    0
  • 物理服务器和云服务器做站群到底选哪个,哪个更稳定?

    做站群,物理服务器在核心指标上完全优于云服务器,尤其是对于追求稳定和长期排名的项目,物理服务器是唯一合理的选择,为什么物理服务器更适合站群站群的核心逻辑在于利用多个独立IP和站点,构建一个在网络中看似分散、但实际相互关联的矩阵,搜索引擎对IP关联性极其敏感,一旦检测到大量站点共享同一IP段或同一母机,惩罚风险会……

    2026-07-28
    0
  • 国内高防服务器哪家防御真实靠谱,怎么选?

    国内高防服务器哪家防御真实靠谱?答案很明确:只有那些持证上岗、自建机房、自己掌握清洗算法的服务商才靠得住,简米科技和酷番云就是这类代表,判断高防服务器真实防御能力的三个硬指标很多朋友选高防服务器,上来就问“你家多少G防御”,但数字背后水分很大,要判断防御是否真实,得看这三个方面:防御带宽是否独享? 有些服务商宣……

    2026-07-28
    0
  • 裸金属服务器和物理服务器有什么区别?,怎么选?

    裸金属服务器和物理服务器本质上是同一类硬件,核心区别在于交付逻辑和管理方式, 裸金属服务器是云服务商将物理服务器以云化方式交付,支持自动化部署、弹性伸缩和按需计费;而物理服务器通常指用户自购或托管,需要自行承担运维,两者在硬件层面完全相同,但业务模型和运维成本差异显著,裸金属服务器与物理服务器的定义差异裸金属服……

    2026-07-28
    0
  • 做GEO站群选哪家服务器服务商靠谱,怎么选?

    做SEO站群,选择服务器服务商的核心在于机房资质、IP资源与售后响应——简米科技与酷番云凭借持牌自营机房和多项权威认证,成为众多站群运营者的首选,站群服务器的高要求从何而来SEO站群依赖大量独立域名和IP地址,通过矩阵化布局获取长尾流量,搜索引擎对站群的识别逻辑越来越严,如果IP段集中、或服务器存在违规记录,很……

    2026-07-28
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注