惊雷无声 发表于 昨天 16:42

HarmonyOS 线程解说(任务分发、线程通信)_鸿蒙开发线程怎么用

② ParallelTaskDispatcher

并发任务分发器,(音译:佩尔楼 他死 diss 怕球儿~)由 Ability 执行 createParallelTaskDispatcher()创建并返回。与GlobalTaskDispatcher 差别的是,ParallelTaskDispatcher 不具有全局唯一性,可以创建多个。开发者在创建或销毁 dispatcher 时,需要持有对应的对象引用 。
/**   * 创建并发任务分发器   
* @param name名称   
* @param priority优先级   
* @return parallelTaskDispatcher   
*/   

public TaskDispatcher createParallelTaskDispatcher(String name, TaskPriority priority) {
      throw new RuntimeException("Stub!");
   }

创建时传两个参数,一个字符串的名字,一个是品级优先级,这里我用null也可以的。这里你又可以想一下为什么需要多一个名字参数,当然是为了区别差别的并发任务分布器,不过至于可不可以重名我就不知道了,理论上来说,应该不允许重名,说不定会给你报错,可以本身去尝试。
https://img-blog.csdnimg.cn/img_convert/0a0d86c6b348e7625842055cb671af01.webp?x-oss-process=image/format,png
③ SerialTaskDispatcher

串行任务分发器(音译:C瑞尔 他死 diss 怕球儿~)由 Ability 执行 createSerialTaskDispatcher()创建并返回。由该分发器分发的所有的任务都是按序次执行,但是执行这些任务的线程并不是固定的。如果要执行并行任务,应使用 ParallelTaskDispatcher 或者 GlobalTaskDispatcher,而不是创建多个SerialTaskDispatcher。如果任务之间没有依赖,应使用 GlobalTaskDispatcher 来实现。它的创建和销毁由开发者本身管理,开发者在使用期间需要持有该对象引用。你可以把它理解成一个有序列表,但是列表里面的值是可变的。它的方法如下:
/**   
* 创建串行任务分发器   
* @param name 名字   
* @param priority 优先级   
* @return SerialTaskDispatcher   
*/   
public TaskDispatcher createSerialTaskDispatcher(String name, TaskPriority priority) {
      throw new RuntimeException("Stub!");
}

获取方法
https://img-blog.csdnimg.cn/img_convert/39a806d6912bd3046956d55e573ecf6c.webp?x-oss-process=image/format,png
④ SpecTaskDispatcher

专有任务分发器(音译:思拜客 他死 diss 怕球儿~) 专有任务分发器,绑定到专有线程上的任务分发器。现在已有的专有线程是主线程。
UITaskDispatcher 和 MainTaskDispatcher 都属于 SpecTaskDispatcher。发起使用UITaskDispatcher。
UITaskDispatcher:绑定到应用主线程的专有任务分发器, 由 Ability 执行getUITaskDispatcher()创建并返回。 由该分发器分发的所有的任务都是在主线程上按序次执行,它在应用步伐结束时被销毁。之前我们说主线程上不能执行过多的任务,那么这个分发器就可以绑定到主线程上,进而可以执行许多任务,你可以这么理解。方法如下:
\*\* \* 获取主线程任务分发器 \
* @return MainTaskDispatcher \
*/
public final TaskDispatcher getMainTaskDispatcher() {
throw new RuntimeException("Stub!");
}
\*\* \* 获取UI线程任务分发器 \
* @return UITaskDispatcher \
*/
public final TaskDispatcher getUITaskDispatcher() {
throw new RuntimeException("Stub!");
}

⑤ 同步派发任务(syncDispatch)

就是一个同步举行的线程,下面由globalTaskDispatcher来派发同步任务。
修改MainAbility。
//日志private static final HiLogLabel label = new HiLogLabel(3, 0xD001100, "ThreadDemo");
private TaskDispatcher globalTaskDispatcher;
@Override    public void onStart(Intent intent) {      super.onStart(intent);
       super.setMainRoute(MainAbilitySlice.class.getName());      
//获取全局并发任务分发器一个应用程序只有一个      globalTaskDispatcher = getGlobalTaskDispatcher(TaskPriority.DEFAULT);
       //GlobalTaskDispatcher 派发同步任务      
syncTask();   
}

syncTask方法中中派发三个同步任务,打印日志
\*\* \* GlobalTaskDispatcher 派发同步任务 \*/

private void syncTask() {
globalTaskDispatcher.syncDispatch(new Runnable() {
@Override public void run() {
HiLog.info(label, "sync task1 run");
}
}
);
HiLog.info(label, "after sync task1"); globalTaskDispatcher.syncDispatch(new Runnable() {
@Override public void run() {
HiLog.info(label,"sync task2 run");
    }
}
);
HiLog.info(label,"after sync task2"); globalTaskDispatcher.syncDispatch(new Runnable() {
@Override public void run() {
HiLog.info(label,"sync task3 run");
    }
   }
);
HiLog.info(label,"after sync task3");
}

运行之后,日志如下所示:
https://img-blog.csdnimg.cn/img_convert/3ef8b367c710c29a1b880dd1000d0199.webp?x-oss-process=image/format,png
虽然现在是没有问题,但是如果对 syncDispatch 使用不当, 将会导致死锁。如下情形可能导致死锁发生:
在专有线程上,利用该专有任务分发器举行 syncDispatch。
在被某个串行任务分发器(dispatcher_a)派发的任务中,再次利用同一个串行任务分发器(dispatcher_a)对象派发任务。
被某个串行任务分发器(dispatcher_a)派发的任务中,颠末数次派发任务,最终又利用该(dispatcher_a)串行任务分发器派发任务。例如:dispatcher_a 派发的任务使用 dispatcher_b 举行任务的派发,在 dispatcher_b 派发的任务中又利用 dispatcher_a 举行派发任务。
行任务分发器(dispatcher_a)派发的任务中利用串行任务分发器(dispatcher_b)举行同步派发任务,同时dispatcher_b 派发的任务中利用串行任务分发器(dispatcher_a)举行同步派发任务。在特定的线程执行序次下将导致死锁。
⑥ 异步派发任务(asyncDispatch)

写一个asyncTask方法,里面的内容和syncTask差不多。
/\*\* \* GlobalTaskDispatcher 派发同步任务
\*/
private void asyncTask() {
globalTaskDispatcher.asyncDispatch(new Runnable() {
@Override public void run() {
HiLog.info(label,"sync task1 run");
}
});
HiLog.info(label,"after sync task1");
}

然后在onStart中调用即可
https://img-blog.csdnimg.cn/img_convert/9166faf500f6aa1df1ea0f3f23a67588.webp?x-oss-process=image/format,png
然后再运行。
https://img-blog.csdnimg.cn/img_convert/18fa0b76b883b0e659e9f312daefb677.webp?x-oss-process=image/format,png
同时这个异步派发是任务是可以取消的。Revocable,globalTaskDispatcher.asyncDispatch的返回值就是Revocable,
https://img-blog.csdnimg.cn/img_convert/234fca6a9347117faa7f6363b640bbbf.webp?x-oss-process=image/format,png
那么上面async中的代码就可以这样写。如下所示:
    /**   * GlobalTaskDispatcher 派发同步任务   */    private void asyncTask() {
      Revocable revocable = globalTaskDispatcher.asyncDispatch(new Runnable() {
         @Override            public void run() {
                HiLog.info(label, "async task1 run");
            }
      });      //撤销任务分发
      revocable.revoke();
      HiLog.info(label, "after async task1");
   }

在运行一下:
https://img-blog.csdnimg.cn/img_convert/2f96bc8ba07993c28f1a0834a7a732db.webp?x-oss-process=image/format,png
很显着里面的任务已经撤销了
⑦ 异步延伸派发任务(delayDispatch)

异步延伸派发任务:异步执行,函数立即返回,内部会在延时指定时间后将任务派发到相应队列中。延时时间参数仅代表在这段时间以后任务分发器会将任务加入到队列中,任务的实际执行时间可能晚于这个时间。具体比这个数值晚多久,取决于队列及内部线程池的繁忙情况。下面用代码演示一下:
    /**   * 当前时间   */   
final long currentTime = System.currentTimeMillis();    /**   * 延迟时间 100ms   */   
final long delayTime = 100;

https://img-blog.csdnimg.cn/img_convert/3b966d23478ea1f55baf307dc58987ab.webp?x-oss-process=image/format,png
delayTask方法如下:
/\*\* \* GlobalTaskDispatcher 派发异步延时任务 \*/
private void delayTask() {
globalTaskDispatcher.delayDispatch(new Runnable() {
@Override public void run() {
HiLog.info(label, "delay task1 run");
final long actualDelayMs = System.currentTimeMillis() - currentTime; HiLog.info(label,"actualDelayTime >= delayTime : " + (actualDelayMs >= delayTime));
   }
   },delayTime); HiLog.info(label, "after delay task1");
}

日志如下:
https://img-blog.csdnimg.cn/img_convert/0f8683fb9f43d1bf5dd24a8f9d7d0759.webp?x-oss-process=image/format,png
⑧ 任务组(Group)

表现一组任务,且该组任务之间有肯定的联系,由 TaskDispatcher 执行createDispatchGroup 创建并返回,代码如下所示。
/\*\* \* 任务组 \*/
private void taskGroup(Context context) {
//创建并发任务分发器
TaskDispatcher dispatcher = context.createParallelTaskDispatcher("parallelTaskDispatcher", TaskPriority.DEFAULT);
//创建任务组
Group group = dispatcher.createDispatchGroup();
// 将任务 1 加入任务组,
dispatcher.asyncGroupDispatch(group,new Runnable() {
@Override public void run() {
HiLog.info(label,"download task1 is running");
}
}
); // 将任务 2 加入任务组, dispatcher.asyncGroupDispatch(group, new Runnable() {
@Override public void run() {
HiLog.info(label,"download task2 is running"); } }); // 在任务组中的所有任务执行完成后执行指定任务。
dispatcher.groupDispatchNotify(group, new Runnable() {
@Override public void run() {
HiLog.info(label, "the close task is running after all tasks in the group are completed");
   }
});
}

onStart方法中调用
https://img-blog.csdnimg.cn/img_convert/1518181a0ba82c8e8d9ace37e711e2a0.webp?x-oss-process=image/format,png
运行效果如下,我运行了两次,两次日志是不一样的,如果里面执行的业务是不一样的,则耗时长的后完成。
https://img-blog.csdnimg.cn/img_convert/9eedd71651fa3091dddab8d7f62d21be.webp?x-oss-process=image/format,png
⑨ 取消任务(Revocable)

Revocable 是取消一个异步任务的接口。异步任务包罗通过 asyncDispatch、delayDispatch、asyncGroupDispatch 派发的任务。如果任务已经在执行中或执行完成,则会返回取消散败。
    /**   * 取消异步任务   */
    private void revocableAsyncTask(Context context) {
      TaskDispatcher dispatcher = context.getUITaskDispatcher();
      Revocable revocable = dispatcher.delayDispatch(new Runnable() {
            @Override
   public void run() {
                HiLog.info(label, "delay dispatch");
         }
       },
10);
      boolean revoked = revocable.revoke();      HiLog.info(label, "" + revoked);   
}

在onStart()中调用
//取消异步任务revocableAsyncTask(MainAbility.this);

运行效果如下:
https://img-blog.csdnimg.cn/img_convert/7e512dd11369bab890574cf451445665.webp?x-oss-process=image/format,png
⑩ 同步设置屏障任务 (syncDispatchBarrier)

在任务组上设立任务执行屏障,同步等候任务组中的所有任务执行完成,再执行指定任务。在全局并发任务分发器(GlobalTaskDispatcher)上同步设置任务屏障,将不会起到屏障作用。就比如说测验提前交卷,A提前20分钟,B提前10分钟,但你只是脱离了考室,离不开科场,这个科场的门就是这个屏障,无论你是提前多久,你都要等到所有考生考完,老师收卷之后才华脱离科场,就是这么一个理。代码如下:
/\*\* \* 同步设置屏障任务 \*/
private void setSyncDispatchBarrier(Context context) {
TaskDispatcher dispatcher= context.createParallelTaskDispatcher("parallelTask",TaskPriority.DEFAULT);
//创建任务组
Group group = dispatcher.createDispatchGroup(); //将任务1加入任务组
dispatcher.asyncGroupDispatch(group, new Runnable() {
@Override public void run() {
HiLog.info(label,"task1 is running");
   }
}); //将任务2加入任务组
dispatcher.asyncGroupDispatch(group, new Runnable() {
   @Override public void run() {
HiLog.info(label,"task2 is running");
}
});
dispatcher.asyncDispatchBarrier(new Runnable() {
@Override public void run() {
   HiLog.info(label,"Barrier");
   }
});
HiLog.info(label,"after syncDispatchBarrier");
}

在onStart()中调用,
//同步设置屏障任务setSyncDispatchBarrier(MainAbility.this);

运行
https://img-blog.csdnimg.cn/img_convert/64d516bf8a8e9c898f30efcfe7213a64.webp?x-oss-process=image/format,png
⑪ 异步设置屏障任务 (asyncDispatchBarrier)

在任务组上设立任务执行屏障后直接返回,指定任务将在任务组中的所有任务执行完成后再执行。在全局并发任务分发器(GlobalTaskDispatcher)上异步设置任务屏障,将不会起到屏障作用。可以使用并发任务分发器(ParallelTaskDispatcher)分离差别的任务组,达到微观并行、宏观串行的举动。
/\*\* \* 异步设置屏障任务 \*/
private void setAsyncDispatchBarrier(Context context) {
TaskDispatcher dispatcher = context.createParallelTaskDispatcher("AsyncParallelTaskDispatcher", TaskPriority.DEFAULT); // 创建任务组
Group group = dispatcher.createDispatchGroup(); //将任务1加入任务组
dispatcher.asyncGroupDispatch(group, new Runnable() {
@Override public void run() {
HiLog.info(label, "task1 is running"); // 1
}
});
//将任务2加入任务组 dispatcher.asyncGroupDispatch(group, new Runnable() {
@Override public void run() {
HiLog.info(label, "task2 is running"); // 2
} });
dispatcher.asyncDispatchBarrier(new Runnable() {
@Override public void run() {
HiLog.info(label, "barrier"); // 3
} });
HiLog.info(label, "after syncDispatchBarrier"); // 4
}

在onStart()中调用
//异步设置屏障任务setAsyncDispatchBarrier(MainAbility.this);

运行效果
https://img-blog.csdnimg.cn/img_convert/5fa49007ed47923b94591cc148e1600c.webp?x-oss-process=image/format,png
⑫ 执行多次任务(applyDispatch)

对指定任务执行多次
/\*\* \* 执行多次任务 \*/ p
rivate void multipleTasks() { //总执行次数
final int total = 10; //倒数计时器
final CountDownLatch latch = new CountDownLatch(total); //长整形列表数组
final ArrayList<Long> indexList = new ArrayList<>(total); TaskDispatcher dispatcher = createParallelTaskDispatcher("dispatcher", TaskPriority.DEFAULT); //执行多次任务
dispatcher.applyDispatch((index) -> {
indexList.add(index); latch.countDown();
HiLog.info(label, "long: "+index); },
total);
//设置任务超时
try { latch.await(); }
catch (InterruptedException e) {
HiLog.info(label, "latch exception");
} //返回true则说明执行了10次
HiLog.info(label, "list size matches," + (total == indexList.size()));
}

运行效果如下:
https://img-blog.csdnimg.cn/img_convert/14cf0c19a2bf762800d57fba97fed62d.webp?x-oss-process=image/format,png
三、线程通信

在开发过程中,开发者经常需要在当前线程中处理下载任务等较为耗时的利用,但是又不希望当前的线程受到壅闭。此时,就可以使用 EventHandler 机制。EventHandler 是HarmonyOS 用于处理线程间通信的一种机制,可以通过 EventRunner 创建新线程,将耗时的利用放到新线程上执行。这样既不壅闭原来的线程,任务又可以得到合理的处理。比如:主线程使用 EventHandler 创建子线程,子线程做耗时的下载图片利用,下载完成后,子线程通过 EventHandler 通知主线程,主线程再更新 UI。
① EventRunner

EventRunner 是一种事故循环器,循环处理从该 EventRunner 创建的新线程的事故队列中获取 InnerEvent 事故或者 Runnable 任务。InnerEvent 是 EventHandler 投递的事故。
EventHandler 是一种用户在当前线程上投递 InnerEvent 事故或者 Runnable 任务到异步线程上处理的机制。每一个 EventHandler 和指定的 EventRunner 所创建的新线程绑定,并且该新线程内部有一个事故队列。EventHandler 可以投递指定的 InnerEvent 事故或 Runnable 任务到这个事故队列。EventRunner 从事故队列里循环地取出事故,如果取出的事故是InnerEvent 事故,将在 EventRunner 地点线程执行 processEvent 回调;如果取出的事故是Runnable 任务,将在 EventRunner 地点线程执行 Runnable 的 run 回调。
② EventHandler

EventHandler 有两个主要作用:
在差别线程间分发和处理 InnerEvent 事故或 Runnable 任务。
延伸处理 InnerEvent 事故或 Runnable 任务。
EventHandler 的运作机制如下图所示:
https://img-blog.csdnimg.cn/img_convert/00726f4e1b5b9441c809ccb6c3e58afc.webp?x-oss-process=image/format,png
使用 EventHandler 实现线程间通信的主要流程:
EventHandler 投递具体的 InnerEvent 事故或者 Runnable 任务到 EventRunner 所创建的线程的事故队列。
EventRunner 循环从事故队列中获取 InnerEvent 事故或者 Runnable 任务。
处理事故或任务:
① 如果 EventRunner 取出的事故为 InnerEvent 事故,则触发 EventHandler 的回调方法并触发 EventHandler 的处理方法,在新线程上处理该事故。
② 如果 EventRunner 取出的事故为 Runnable 任务,则 EventRunner 直接在新线程上处理 Runnable 任务。
1. 约束限定

在举行线程间通信的时候,EventHandler 只能和 EventRunner 所创建的线程举行绑定,EventRunner 创建时需要判断是否创建乐成,只有确保获取的 EventRunner 实例非空时,才可以使用 EventHandler 绑定 EventRunner。
一个 EventHandler 只能同时与一个 EventRunner 绑定,一个 EventRunner 上可以创建多个 EventHandler。
2. 开发场景

EventHandler 的主要功能是将 InnerEvent 事故或者 Runnable 任务投递到其他的线程举行处理,其使用的场景包罗
开发者需要将 InnerEvent 事故投递到新的线程,按照优先级和延时举行处理。投递时,EventHandler 的优先级可在IMMEDIATE、HIGH、LOW、IDLE 中选择,并设置合适的 delayTime。
开发者需要将 Runnable 任务投递到新的线程,并按照优先级和延时举行处理。投递时,EventHandler 的优先级可在IMMEDIATE、HIGH、LOW、IDLE 中选择,并设置合适的 delayTime。
开发者需要在新创建的线程里投递事故到原线程举行处理。
3. 工作模式

EventRunner 的工作模式可以分为托管模式和手动模式。两种模式是在调用 EventRunner 的create()方法时,通过选择差别的参数来实现的,默认为托管模式。
托管模式:不需要开发者调用 run()和 stop()方法去启动和停止 EventRunner。当 EventRunner 实例化时,体系调用
run()来启动 EventRunner;当 EventRunner 不被引用时,体系调用 stop()来停止 EventRunner。
手动模式:需要开发者自行调用 EventRunner 的 run()方法和 stop()方法来确保线程的启动和停止。
③ 接口说明

1. EventHandler

EventHandler 的属性 Priority(优先级)介绍:
EventRunner 将根据优先级的高低从事故队列中获取事故或者 Runnable 任务举行处理。
属性描述Priority.IMMEDIATE表现事故被立即投递Priority.HIGH表现事故先于 LOW 优先级投递Priority.LOW表现事故优于 IDLE 优先级投递,事故的默认优先级是 LOWPriority.IDLE表现在没有其他事故的情况下,才投递该事故

[*]EventHandler 的主要接口介绍:
https://img-blog.csdnimg.cn/img_convert/fe0075e4049390c132df9d33c5ba798b.webp?x-oss-process=image/format,png
https://img-blog.csdnimg.cn/img_convert/2291098d41cf95147517544b1642869f.webp?x-oss-process=image/format,png
2. EventRunner



[*]EventRunner 的主要接口介绍:
https://img-blog.csdnimg.cn/img_convert/01611c510a42ef8572a7a75780d7623e.webp?x-oss-process=image/format,png
3. InnerEvent



[*]InnerEvent 的属性介绍:
属性描述eventId事故的 ID, 由开发者定义用来辨别事故object事故携带的 Object 信息param事故携带的 long 型数据

[*]InnerEvent 的主要接口介绍:
https://img-blog.csdnimg.cn/img_convert/0cebfa3ba50e11a3b1dddadeb1b7af44.webp?x-oss-process=image/format,png
④ 开发步调

一、EventHandler 投递 InnerEvent 事故

EventHandler 投递 InnerEvent 事故,并按照优先级和延时举行处理,创建一个MyEventHandler类型继续EventHandler
https://img-blog.csdnimg.cn/img_convert/73f637f8f69425c15610fe4c3f988192.webp?x-oss-process=image/format,png
package com.llw.thread.event;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
public class MyEventHandler extends EventHandler {
/\*\* \* 日志 \*/
private static final HiLogLabel label = new HiLogLabel(3, 0xD001100, "ThreadDemo");
public MyEventHandler(EventRunner runner)
throws IllegalArgumentException { super(runner);
}
/\*\* \* 1. 创建 EventHandler 的子类,在子类中重写实现方法 processEvent()来处理事件 \*
\* @param event \*/
@Override
protected void processEvent(InnerEvent event) {
super.processEvent(event);
if (event == null) { return; }
int eventId = event.eventId;
long param = event.param;
switch ((int) (eventId | param)) {
case 1: HiLog.info(label, "eventId | param --->" + 1);
break;
default: break; }
} /\*\* \* EventHandler 投递 InnerEvent 事件 \*/
private void initInnerEvent() {
//2. 创建 EventRunner,以手动模式为例。
// create()的参数是 true 时,则为托管模式
EventRunner runner = EventRunner.create(false);
if (runner == null) { return; }   //3. 创建 EventHandler 子类的实例。
MyEventHandler myHandler = new MyEventHandler(runner); //4. 获取 InnerEvent 事件。
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); //5. 投递事件,投递的优先级以 IMMEDIATE 为例,延时选择 0ms 和 2ms。
myHandler.sendEvent(event1, 0, EventHandler.Priority.IMMEDIATE); // 延时 2ms 后立即处理
myHandler.sendEvent(event2, 2, EventHandler.Priority.IMMEDIATE); //6. 启动和停止 EventRunner,如果为托管模式,则不需要此步骤。
runner.run(); //待执行操作
// ... 执行业务逻辑
// 停止
EventRunner runner.stop();
}
}

二、EventHandler 投递 Runnable 任务

/\*\* \* EventHandler 投递 Runnable 任务 \*/
private void initRunnable() {
//2. 创建 EventRunner,以手动模式为例。
// create()的参数是 true 时,则为托管模式
EventRunner runner = EventRunner.create(false); if (runner == null) { return; }
//3. 创建 EventHandler 子类的实例。
MyEventHandler myHandler = new MyEventHandler(runner);
//2. 创建 Runnable 任务。
Runnable task1 = new Runnable() {
@Override public void run() { HiLog.info(label, "task1 running"); } };
Runnable task2 = new Runnable() {
@Override public void run() {
HiLog.info(label, "task1 running");
}
}; //3. 投递 Runnable 任务,投递的优先级以 IMMEDIATE 为例,延时选择 0ms 和 2ms。
myHandler.postTask(task1, 0, EventHandler.Priority.IMMEDIATE); // 延时 2ms 后立即执行
myHandler.postTask(task2, 2, EventHandler.Priority.IMMEDIATE); //4. 启动和停止 EventRunner,如果是托管模式,则不需要此步骤。 runner.run();
//待执行操作
// ... 执行业务逻辑
// 停止
EventRunner runner.stop();
}

三、在新创建的线程里投递事故到原线程

修改MyEventHandler之子女码如下:
package com.llw.thread.event;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
public class MyEventHandler extends EventHandler {
/\*\* \* 日志 \*/
private static final HiLogLabel label = new HiLogLabel(3, 0xD001100, "ThreadDemo");
private MyEventHandler myHandler;
private EventRunner runner;
public MyEventHandler(EventRunner runner) throws IllegalArgumentException {
super(runner); } /\*\* \* 1. 创建 EventHandler 的子类,在子类中重写实现方法 processEvent()来处理事件 \* \* @param event \*/ @Override
protected void processEvent(InnerEvent event) {
super.processEvent(event);
if (event == null) { return; }
int eventId = event.eventId;
long param = event.param;
Object object = event.object; switch ((int) (eventId | param)) {
   case 1: HiLog.info(label, "eventId | param --->" + 1);
break;
case 2: EventRunner runner2 = null; // 将原先线程的 EventRunner 实例投递给新创建的线程
if (object instanceof EventRunner) {
//强转 runner2 = (EventRunner) object;
} // 将原先线程的 EventRunner 实例与新创建的线程的 EventHandler 绑定
EventHandler myHandler2 = new EventHandler(runner2) {
@Override protected void processEvent(InnerEvent event) {
//需要在原先线程执行的操作
}
};
int eventId2 = 1; long param2 = 0;
Object object2 = null;
InnerEvent event2 = InnerEvent.get(eventId2, param2, object2); // 投递事件到原先的线程
myHandler2.sendEvent(event2);
break; default: break; }
} /\*\* \* EventHandler 投递 InnerEvent 事件 \*/
private void initInnerEvent() {
//2. 创建 EventRunner,以手动模式为例。 // create()的参数是 true 时,则为托管模式
runner = EventRunner.create(false);
if (runner == null) { return; } //3. 创建 EventHandler 子类的实例。
myHandler = new MyEventHandler(runner);
//4. 获取 InnerEvent 事件。
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);
//5. 投递事件,投递的优先级以 IMMEDIATE 为例,延时选择 0ms 和 2ms。
myHandler.sendEvent(event1, 0, EventHandler.Priority.IMMEDIATE); // 延时 2ms 后立即处理
myHandler.sendEvent(event2, 2, EventHandler.Priority.IMMEDIATE); //6. 启动和停止 EventRunner,如果为托管模式,则不需要此步骤。


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