不同应用在各自独立的进程中运行。当应用以任何形式启动时,系统为其创建进程,该进程将持续运行。当进程完成当前任务处于等待状态,且系统资源不足时,系统自动回收。

在启动应用时,系统会为该应用创建一个称为“主线程”的执行线程。该线程随着应用创建或消失,是应用的核心线程。UI 界面的显示和更新等操作,都是在主线程上进行。
主线程又称 UI 线程,默认情况下,所有的操作都是在主线程上执行。如果需要执行比较耗时的任务(如下载文件、查询数据库),可创建其他线程来处理。
如果应用的业务逻辑比较复杂,可能需要创建多个线程来执行多个任务。这种情况下,代码复杂难以维护,任务与线程的交互也会更加繁杂。
要解决此问题,开发者可以使用 TaskDispatcher 来分发不同的任务。
TaskDispatcher 介绍
TaskDispatcher 是一个任务分发器,它是 Ability 分发任务的基本接口,隐藏任务所在线程的实现细节。
为保证应用有更好的响应性,我们需要设计任务的优先级。在 UI 线程上运行的任务默认以高优先级运行,如果某个任务无需等待结果,则可以用低优先级。
线程优先级介绍:
HIGH:最高任务优先级,比默认优先级、低优先级的任务有更高的几率得到执行。
DEFAULT:默认任务优先级, 比低优先级的任务有更高的几率得到执行。
LOW:低任务优先级,比高优先级、默认优先级的任务有更低的几率得到执行。
TaskDispatcher 具有多种实现,每种实现对应不同的任务分发器。在分发任务时可以指定任务的优先级,由同一个任务分发器分发出的任务具有相同的优先级。
系统提供的任务分发器有:
GlobalTaskDispatcher
ParallelTaskDispatcher
SerialTaskDispatcher
SpecTaskDispatcher
实践
①同步派发任务 syncDispatch
/**
* 同步派发任务
*/
private void syncDispatch() {
TaskDispatcher globalTaskDispatcher = getGlobalTaskDispatcher(TaskPriority.DEFAULT);
globalTaskDispatcher.syncDispatch(new Runnable() {
@Override
public void run() {
HiLog.info(LABEL_LOG, "sync task1 run");
}
});
HiLog.info(LABEL_LOG, "after sync task1");
globalTaskDispatcher.syncDispatch(new Runnable() {
@Override
public void run() {
HiLog.info(LABEL_LOG, "sync task2 run");
}
});
HiLog.info(LABEL_LOG, "after sync task2");
globalTaskDispatcher.syncDispatch(new Runnable() {
@Override
public void run() {
HiLog.info(LABEL_LOG, "sync task3 run");
}
});
HiLog.info(LABEL_LOG, "after sync task3");
}
运行之后查看日志:

在专有线程上,利用该专有任务分发器进行 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
派发任务,并立即返回,返回值是一个可用于取消任务的接口。
/**
* 异步派发任务
*/
private void asyncDispatch() {
TaskDispatcher globalTaskDispatcher = getGlobalTaskDispatcher(TaskPriority.DEFAULT);
Revocable revocable = globalTaskDispatcher.asyncDispatch(new Runnable() {
@Override
public void run() {
HiLog.info(LABEL_LOG, "async task1 run");
}
});
HiLog.info(LABEL_LOG, "after async task1");
}
运行之后查看日志:

③异步延迟派发任务 delayDispatch
具体比这个数值晚多久,取决于队列及内部线程池的繁忙情况。
/**
* 异步延迟派发任务
*/
private void delayDispatch() {
final long callTime = System.currentTimeMillis();
final long delayTime = 50L;
TaskDispatcher globalTaskDispatcher = getGlobalTaskDispatcher(TaskPriority.DEFAULT);
Revocable revocable = globalTaskDispatcher.delayDispatch(new Runnable() {
@Override
public void run() {
HiLog.info(LABEL_LOG, "delayDispatch task1 run");
final long actualDelay = System.currentTimeMillis() - callTime;
HiLog.info(LABEL_LOG, "actualDelayTime >= delayTime: %{public}b", (actualDelay >= delayTime));
}
}, delayTime);
HiLog.info(LABEL_LOG, "after delayDispatch task1");
}
运行之后查看日志:

程序首先执行"after delayDispatch task1"
然后执行"delayDispatch task1 run"
最后执行"actualDelayTime >= delayTime: %{public}b", (actualDelay >= delayTime)
④任务组 Group
将任务加入任务组,返回一个用于取消任务的接口。
/**
* 任务组
*/
private void dispatchGroup() {
String dispatcherName = "parallelTaskDispatcher";
TaskDispatcher dispatcher = createParallelTaskDispatcher(dispatcherName, TaskPriority.DEFAULT);
// 创建任务组。
Group group = dispatcher.createDispatchGroup();
// 将任务1加入任务组,返回一个用于取消任务的接口。
dispatcher.asyncGroupDispatch(group, new Runnable() {
@Override
public void run() {
HiLog.info(LABEL_LOG, "download task1 is running");
}
});
// 将与任务1相关联的任务2加入任务组。
dispatcher.asyncGroupDispatch(group, new Runnable() {
@Override
public void run() {
HiLog.info(LABEL_LOG, "download task2 is running");
}
});
// 在任务组中的所有任务执行完成后执行指定任务。
dispatcher.groupDispatchNotify(group, new Runnable() {
@Override
public void run() {
HiLog.info(LABEL_LOG, "the close task is running after all tasks in the group are completed");
}
});
}
运行之后查看日志:

⑤同步设置屏障任务 syncDispatchBarrier
在任务组上设立任务执行屏障,同步等待任务组中的所有任务执行完成,再执行指定任务。
/**
* 同步设置屏障任务
*/
private void syncDispatchBarrier() {
String dispatcherName = "parallelTaskDispatcher";
TaskDispatcher dispatcher = createParallelTaskDispatcher(dispatcherName, TaskPriority.DEFAULT);
// 创建任务组。
Group group = dispatcher.createDispatchGroup();
// 将任务加入任务组,返回一个用于取消任务的接口。
dispatcher.asyncGroupDispatch(group, new Runnable() {
@Override
public void run() {
HiLog.info(LABEL_LOG, "task1 is running"); // 1
}
});
dispatcher.asyncGroupDispatch(group, new Runnable() {
@Override
public void run() {
HiLog.info(LABEL_LOG, "task2 is running"); // 2
}
});
dispatcher.syncDispatchBarrier(new Runnable() {
@Override
public void run() {
HiLog.info(LABEL_LOG, "barrier"); // 3
}
});
HiLog.info(LABEL_LOG, "after syncDispatchBarrier"); // 4
}
运行之后查看日志:

⑥异步设置屏障任务 asyncDispatchBarrier
在任务组上设立任务执行屏障后直接返回,指定任务将在任务组中的所有任务执行完成后再执行。
/**
* 异步设置屏障任务
*/
private void asyncDispatchBarrier() {
TaskDispatcher dispatcher = createParallelTaskDispatcher("dispatcherName", TaskPriority.DEFAULT);
// 创建任务组。
Group group = dispatcher.createDispatchGroup();
// 将任务加入任务组,返回一个用于取消任务的接口。
dispatcher.asyncGroupDispatch(group, new Runnable() {
@Override
public void run() {
HiLog.info(LABEL_LOG, "task1 is running"); // 1
}
});
dispatcher.asyncGroupDispatch(group, new Runnable() {
@Override
public void run() {
HiLog.info(LABEL_LOG, "task2 is running"); // 2
}
});
dispatcher.asyncDispatchBarrier(new Runnable() {
@Override
public void run() {
HiLog.info(LABEL_LOG, "barrier"); // 3
}
});
HiLog.info(LABEL_LOG, "after asyncDispatchBarrier"); // 4
}
运行之后查看日志:

总结
👇
一周年庆 抽奖活动

关注鸿蒙技术社区订阅号,转发此图文至朋友圈,公众号回复转发的截图,抽鸿蒙新款 matepad11、价值 399、299 元的鸿蒙盲盒和 2000ml 健康随身杯!
回复“周年庆”抽奖
👇

点“阅读原文”了解更多




