十念 发表于 2024-10-20 04:13:12

鸿蒙OS 线程间通讯

鸿蒙OS 线程间通讯概述

在开辟过程中,开辟者经常必要在当前线程中处理下载使命等较为耗时的操纵,但是又不盼望当前的线程受到壅闭。此时,就可以使用 EventHandler 机制。EventHandler 是 HarmonyOS 用于处理线程间通讯的一种机制,可以通过 创建新线程,将耗时的操纵放到新线程上执行。这样既不壅闭原来的线程,使命又可以得到公道的处理。比如:主线程使用 EventHandler 创建子线程,子线程做耗时的下载图片操纵,下载完成后,子线程通过 EventHandler 通知主线程,主线程再更新 UI。
根本概念
EventRunner 是一种变乱循环器,循环处理从该 EventRunner 创建的新线程的变乱队列中获取 InnerEvent 变乱或者 Runnable 使命。InnerEvent 是 EventHandler 投递的变乱。
EventHandler 是一种用户在当前线程上投递 InnerEvent 变乱或者 Runnable 使命到异步线程上处理的机制。每一个 EventHandler 和指定的 EventRunner 所创建的新线程绑定,并且该新线程内部有一个变乱队列。EventHandler 可以投递指定的 InnerEvent 变乱或 Runnable 使命到这个变乱队列。EventRunner 从变乱队列里循环地取出变乱,假如取出的变乱是 InnerEvent 变乱,将在 EventRunner 所在线程执行 processEvent 回调;假如取出的变乱是 Runnable 使命,将在 EventRunner 所在线程执行 Runnable 的 run 回调。一般,EventHandler 有两个重要作用:
在不同线程间分发和处理 InnerEvent 事件或 Runnable 任务。
延迟处理 InnerEvent 事件或 Runnable 任务。
运作机制
EventHandler 的运作机制如下图所示:
https://i-blog.csdnimg.cn/direct/1a4b758378e4471096eb01b52aecc664.png
使用 EventHandler 实现线程间通讯的重要流程:
EventHandler 投递具体的 InnerEvent 变乱或者 Runnable 使命到 EventRunner 所创建的线程的变乱队列。
EventRunner 循环从变乱队列中获取 InnerEvent 变乱或者 Runnable 使命。
处理变乱或使命:
如果 EventRunner 取出的事件为 InnerEvent 事件,则触发 EventHandler 的回调方法并触发 EventHandler 的处理方法,在新线程上处理该事件。
如果 EventRunner 取出的事件为 Runnable 任务,则 EventRunner 直接在新线程上处理 Runnable 任务。
束缚限制
在举行线程间通讯的时间,EventHandler 只能和 EventRunner 所创建的线程举行绑定,EventRunner 创建时必要判断是否创建乐成,只有确保获取的 EventRunner 实例非空时,才可以使用 EventHandler 绑定 EventRunner。
一个 EventHandler 只能同时与一个 EventRunner 绑定,一个 EventRunner 上可以创建多个 EventHandler。
鸿蒙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 使命举行处理。
https://i-blog.csdnimg.cn/direct/52c34c1ecafb4b3d975d91135e5c130e.png
EventHandler 的重要接口介绍:
https://i-blog.csdnimg.cn/direct/05bf8da67f3b49819c35c1231cf57f98.png
EventRunner
EventRunner的重要接口介绍:
https://i-blog.csdnimg.cn/direct/4d8b050943304dea8f9b2658be9d1d5e.png
InnerEvent
InnerEvent的属性介绍:
https://i-blog.csdnimg.cn/direct/b6a4f5235bbc4e88afacefafbb75ae1a.png
InnerEvent的重要接口介绍:
https://i-blog.csdnimg.cn/direct/384611ec8a274167bc01c964299a108a.png
开辟步骤
EventHandler 投递 InnerEvent 变乱
EventHandler 投递 InnerEvent 变乱,并按照优先级和延时举行处理,开辟步骤如下:
创建 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;
       }
       }
   }
创建 EventRunner,以手动模式为例。
EventRunner runner = EventRunner.create(false);// create()的参数是 true时,则为托管模式
   // 需要对 EventRunner 的实例进行校验,因为创建 EventRunner 可能失败,如创建线程失败时,创建 EventRunner 失败。
   if (runner == null) {
       return;
   }
创建 EventHandler 子类的实例。
MyEventHandler myHandler = new MyEventHandler(runner);
获取 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);
投递变乱,投递的优先级以 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 后立即处理
启动和停止 EventRunner,假如为托管模式,则不必要此步骤。
runner.run();
   //待执行操作
   runner.stop();// 开发者根据业务需要在适当时机停止 EventRunner
EventHandler 投递 Runnable 使命
EventHandler 投递Runnable 使命,并按照优先级和延时举行处理,开辟步骤如下:
创建 EventHandler 的子类,创建 EventRunner,并创建 EventHandler 子类的实例,步骤与[ EventHandler 投递 InnerEvent] 场景的步骤1-3相同。
创建 Runnable 使命。
Runnable task1 = new Runnable() {
       @Override
       public void run() {
         // 待执行的操作,由开发者定义
       }
   };
   Runnable task2 = new Runnable() {
       @Override
       public void run() {
         // 待执行的操作,由开发者定义
       }
   };
投递 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后立即执行
启动和停止 EventRunner,假如是托管模式,则不必要此步骤。
runner.run();
   //待执行操作

   
   runner.stop();// 停止 EventRunner
在新创建的线程里投递变乱到原线程
EventHandler 从新创建的线程投递变乱到原线程并举行处理,开辟步骤如下:
创建 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;
       }
       }
   }
创建 EventRunner,以手动模式为例。
EventRunner runner1 = EventRunner.create(false);// create()的参数是true时,则为托管模式。
   // 需要对 EventRunner 的实例进行校验,不是任何线程都可以通过 create 创建,例如:当线程池已满时,不能再创建线程。
   if (runner1 == null) {
       return;
   }
创建 EventHandler 子类的实例。
   MyEventHandler myHandler1 = new MyEventHandler(runner1);
获取 InnerEvent 变乱。
// 获取事件实例,其属性 eventId, param, object 由开发者确定,代码中只是示例。
   int eventId1 = 0;
   long param = 0;
   Object object = (Object) EventRunner.current();
   InnerEvent event1 = InnerEvent.get(eventId1, param, object);
投递变乱,在新线程上直接处理。
// 将与当前线程绑定的 EventRunner 投递到与 runner1 创建的新线程中myHandler.sendEvent(event1);
启动和停止 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;

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 鸿蒙OS 线程间通讯