HarmonyOS學(xué)習(xí)路之開發(fā)篇—線程管理
1
什么是線程管理
不同應(yīng)用在各自獨(dú)立的進(jìn)程中運(yùn)行。當(dāng)應(yīng)用以任何形式啟動(dòng)時(shí),系統(tǒng)為其創(chuàng)建進(jìn)程,該進(jìn)程將持續(xù)運(yùn)行。當(dāng)進(jìn)程完成當(dāng)前任務(wù)處于等待狀態(tài),且系統(tǒng)資源不足時(shí),系統(tǒng)自動(dòng)回收。
在啟動(dòng)應(yīng)用時(shí),系統(tǒng)會(huì)為該應(yīng)用創(chuàng)建一個(gè)稱為“主線程”的執(zhí)行線程。該線程隨著應(yīng)用創(chuàng)建或消失,是應(yīng)用的核心線程。UI界面的顯示和更新等操作,都是在主線程上進(jìn)行。主線程又稱UI線程,默認(rèn)情況下,所有的操作都是在主線程上執(zhí)行。如果需要執(zhí)行比較耗時(shí)的任務(wù)(如下載文件、查詢數(shù)據(jù)庫(kù)),可創(chuàng)建其他線程來處理。
2
適用場(chǎng)景
如果應(yīng)用的業(yè)務(wù)邏輯比較復(fù)雜,可能需要?jiǎng)?chuàng)建多個(gè)線程來執(zhí)行多個(gè)任務(wù)。這種情況下,代碼復(fù)雜難以維護(hù),任務(wù)與線程的交互也會(huì)更加繁雜。要解決此問題,開發(fā)者可以使用“TaskDispatcher”來分發(fā)不同的任務(wù)。
3
接口說明
TaskDispatcher是一個(gè)任務(wù)分發(fā)器,它是Ability分發(fā)任務(wù)的基本接口,隱藏任務(wù)所在線程的實(shí)現(xiàn)細(xì)節(jié)。在UI線程上運(yùn)行的任務(wù)默認(rèn)以高優(yōu)先級(jí)運(yùn)行,如果某個(gè)任務(wù)無需等待結(jié)果,則可以用低優(yōu)先級(jí)。
表1 線程優(yōu)先級(jí)介紹
| 優(yōu)先級(jí) | 詳細(xì)描述 |
|---|---|
| HIGH | 最高任務(wù)優(yōu)先級(jí),比默認(rèn)優(yōu)先級(jí)、低優(yōu)先級(jí)的任務(wù)有更高的幾率得到執(zhí)行。 |
| DEFAULT | 默認(rèn)任務(wù)優(yōu)先級(jí), 比低優(yōu)先級(jí)的任務(wù)有更高的幾率得到執(zhí)行。 |
| LOW | 低任務(wù)優(yōu)先級(jí),比高優(yōu)先級(jí)、默認(rèn)優(yōu)先級(jí)的任務(wù)有更低的幾率得到執(zhí)行。 |
系統(tǒng)提供的任務(wù)分發(fā)器有GlobalTaskDispatcher、ParallelTaskDispatcher、SerialTaskDispatcher 、SpecTaskDispatcher。
-
GlobalTaskDispatcher 全局并發(fā)任務(wù)分發(fā)器,由Ability執(zhí)行g(shù)etGlobalTaskDispatcher()獲取。適用于任務(wù)之間沒有聯(lián)系的情況。一個(gè)應(yīng)用只有一個(gè)GlobalTaskDispatcher,它在程序結(jié)束時(shí)才被銷毀。 -
ParallelTaskDispatcher 并發(fā)任務(wù)分發(fā)器,由Ability執(zhí)行createParallelTaskDispatcher()創(chuàng)建并返回。與GlobalTaskDispatcher不同,ParallelTaskDispatcher不具有全局唯一性,可以創(chuàng)建多個(gè)。 -
SerialTaskDispatcher 串行任務(wù)分發(fā)器,由Ability執(zhí)行createSerialTaskDispatcher()創(chuàng)建并返回。由該分發(fā)器分發(fā)的所有的任務(wù)都是按順序執(zhí)行,但是執(zhí)行這些任務(wù)的線程并不固定。如果要執(zhí)行并行任務(wù),應(yīng)使用ParallelTaskDispatcher或者GlobalTaskDispatcher,而不是創(chuàng)建多個(gè)SerialTaskDispatcher。 -
SpecTaskDispatcher 專有任務(wù)分發(fā)器,綁定到專有線程上的任務(wù)分發(fā)器。目前已有的專有線程為UI線程,通過UITaskDispatcher進(jìn)行任務(wù)分發(fā)。 -
UITaskDispatcher 綁定到應(yīng)用主線程的專有任務(wù)分發(fā)器, 由Ability執(zhí)行g(shù)etUITaskDispatcher()創(chuàng)建并返回。由該分發(fā)器分發(fā)的所有的任務(wù)都是在主線程上按順序執(zhí)行。
4
開發(fā)使用
-
syncDispatch同步派發(fā)任務(wù):派發(fā)任務(wù)并在當(dāng)前線程等待任務(wù)執(zhí)行完成。
TaskDispatcher globalTaskDispatcher = getGlobalTaskDispatcher(TaskPriority.DEFAULT);
globalTaskDispatcher.syncDispatch(() -> HiLog.info(LABEL_LOG,"Sync task1 run" + System.lineSeparator()));
HiLog.info(LABEL_LOG,"After sync task1" + System.lineSeparator());
globalTaskDispatcher.syncDispatch(() -> HiLog.info(LABEL_LOG,"Sync task2 run" + System.lineSeparator()));
HiLog.info(LABEL_LOG,"After sync task2" + System.lineSeparator());
執(zhí)行結(jié)果:

-
asyncDispatch異步派發(fā)任務(wù):派發(fā)任務(wù),并立即返回。
TaskDispatcher globalTaskDispatcher = getGlobalTaskDispatcher(TaskPriority.DEFAULT);
globalTaskDispatcher.asyncDispatch(() -> {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
HiLog.error(LABEL_LOG, "%{public}s", "AsyncDispatch InterruptedException");
}
HiLog.info(LABEL_LOG,"Async task1 run" + System.lineSeparator());
});
HiLog.info(LABEL_LOG,"After async task1" + System.lineSeparator());
globalTaskDispatcher.asyncDispatch(() -> {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
HiLog.error(LABEL_LOG, "%{public}s", "AsyncDispatch InterruptedException");
}
HiLog.info(LABEL_LOG,"Async task2 run" + System.lineSeparator());
});
HiLog.info(LABEL_LOG,"After async task2" + System.lineSeparator());
執(zhí)行結(jié)果:在兩個(gè)異步執(zhí)行中添加延時(shí),更加體現(xiàn)效果

-
delayDispatch異步延遲派發(fā)任務(wù):異步執(zhí)行,函數(shù)立即返回,內(nèi)部會(huì)在延時(shí)指定時(shí)間后將任務(wù)派發(fā)到相應(yīng)隊(duì)列中。
TaskDispatcher globalTaskDispatcher = getGlobalTaskDispatcher(TaskPriority.DEFAULT);
final long callTime = System.currentTimeMillis();
globalTaskDispatcher.delayDispatch(() -> {
HiLog.info(LABEL_LOG,"DelayDispatch task1 run" + System.lineSeparator());
final long actualDelayMs = System.currentTimeMillis() - callTime;
HiLog.info(LABEL_LOG,"ActualDelayTime >= delayTime : " + (actualDelayMs >= DELAY_TIME));
}, DELAY_TIME);
HiLog.info(LABEL_LOG,"After delayDispatch task1" + System.lineSeparator());
執(zhí)行結(jié)果:延時(shí)時(shí)間參數(shù)僅代表在這段時(shí)間以后任務(wù)分發(fā)器會(huì)將任務(wù)加入到隊(duì)列中,任務(wù)的實(shí)際執(zhí)行時(shí)間可能晚于這個(gè)時(shí)間。具體比這個(gè)數(shù)值晚多久,取決于隊(duì)列及內(nèi)部線程池的繁忙情況。

-
Group任務(wù)組:表示一組任務(wù),且該組任務(wù)之間有一定的聯(lián)系,由TaskDispatcher執(zhí)行createDispatchGroup創(chuàng)建并返回。
TaskDispatcher dispatcher = createParallelTaskDispatcher("", TaskPriority.DEFAULT);
Group group = dispatcher.createDispatchGroup();
dispatcher.asyncGroupDispatch(group, () -> {
HiLog.info(LABEL_LOG,"GroupTask1 is running" + System.lineSeparator());
});
dispatcher.asyncGroupDispatch(group, () -> {
HiLog.info(LABEL_LOG,"GroupTask2 is running" + System.lineSeparator());
});
dispatcher.groupDispatchNotify(group, () -> HiLog.info(LABEL_LOG,
"此任務(wù)在組中的所有任務(wù)完成后運(yùn)行" + System.lineSeparator()));
運(yùn)行結(jié)果:結(jié)果性不確定、沒有執(zhí)行順序可言。


-
Revocable取消任務(wù):Revocable是取消一個(gè)異步任務(wù)的接口。異步任務(wù)包括通過 asyncDispatch、delayDispatch、asyncGroupDispatch 派發(fā)的任務(wù)。
TaskDispatcher dispatcher = getUITaskDispatcher();
Revocable revocable = dispatcher.delayDispatch(() -> {
HiLog.info(LABEL_LOG,"Delay dispatch" + System.lineSeparator());
}, 50);
boolean revoked = revocable.revoke();
HiLog.info(LABEL_LOG,"Revoke result :" + revoked);
運(yùn)行結(jié)果:如果任務(wù)已經(jīng)在執(zhí)行中或執(zhí)行完成,則會(huì)返回取消失敗。

-
syncDispatchBarrier同步設(shè)置屏障任務(wù):在任務(wù)組上設(shè)立任務(wù)執(zhí)行屏障,同步等待任務(wù)組中的所有任務(wù)執(zhí)行完成,再執(zhí)行指定任務(wù)
TaskDispatcher dispatcher = createParallelTaskDispatcher("SyncBarrierDispatcher", TaskPriority.DEFAULT);
Group group = dispatcher.createDispatchGroup();
dispatcher.asyncGroupDispatch(group, () -> {
HiLog.info(LABEL_LOG,"Task1 is running" + System.lineSeparator());
});
dispatcher.asyncGroupDispatch(group, () -> {
HiLog.info(LABEL_LOG,"Task2 is running" + System.lineSeparator());
});
dispatcher.syncDispatchBarrier(() -> {
HiLog.info(LABEL_LOG,"Barrier" + System.lineSeparator());
});
HiLog.info(LABEL_LOG,"After syncDispatchBarrier" + System.lineSeparator());
執(zhí)行結(jié)果:

執(zhí)行20次后結(jié)果:結(jié)果發(fā)現(xiàn)線程執(zhí)行的順序不確定性,有時(shí)會(huì)出現(xiàn)阻塞的現(xiàn)象

-
asyncDispatchBarrier異步設(shè)置屏障任務(wù):在任務(wù)組上設(shè)立任務(wù)執(zhí)行屏障后直接返回。
TaskDispatcher dispatcher = createParallelTaskDispatcher("AsyncBarrierDispatcher", TaskPriority.DEFAULT);
Group group = dispatcher.createDispatchGroup();
dispatcher.asyncGroupDispatch(group, () -> {
HiLog.info(LABEL_LOG,"Task1 is running" + System.lineSeparator());
});
dispatcher.asyncGroupDispatch(group, () -> {
HiLog.info(LABEL_LOG,"Task2 is running" + System.lineSeparator());
});
dispatcher.asyncDispatchBarrier(() -> {
HiLog.info(LABEL_LOG,"Barrier" + System.lineSeparator());
});
HiLog.info(LABEL_LOG,"After asyncDispatchBarrier" + System.lineSeparator());
執(zhí)行結(jié)果:1和2的執(zhí)行順序不定,但總在3之前執(zhí)行;4不需要等待1、2、3執(zhí)行完成。
指定任務(wù)將在任務(wù)組中的所有任務(wù)執(zhí)行完成后再執(zhí)行

-
applyDispatch執(zhí)行多次任務(wù):對(duì)指定任務(wù)執(zhí)行多次。
final CountDownLatch latch = new CountDownLatch(10);
final ArrayList<Long> indexList = new ArrayList<>(10);
TaskDispatcher globalTaskDispatcher = getGlobalTaskDispatcher(TaskPriority.DEFAULT);
//執(zhí)行10次
globalTaskDispatcher.applyDispatch(index -> {
indexList.add(index);
latch.countDown();
}, 10);
//超時(shí)出錯(cuò)
try {
latch.await();
} catch (InterruptedException exception) {
HiLog.error(LABEL_LOG, "%{public}s", "applyDispatchTask InterruptedException");
}
HiLog.info(LABEL_LOG,"List size matches :" + (indexList.size() == TASK_TOTAL));
執(zhí)行結(jié)果:

往期推薦
