鸿蒙开发- 线程(一)

<?xml version="1.0" encoding="utf-8"?>
<!--
 Copyright (c) 2021 Huawei Device Co., Ltd.
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_parent"
    ohos:width="match_parent"
    ohos:alignment="horizontal_center"
    ohos:orientation="vertical"
    ohos:padding="5vp">

    <Button
        ohos:id="$+id:sync_dispatch_button"
        ohos:height="match_content"
        ohos:width="300vp"
        ohos:background_element="$graphic:button_bg"
        ohos:padding="5vp"
        ohos:text="$string:sync_dispatch"
        ohos:text_alignment="center"
        ohos:text_size="18fp"
        ohos:top_margin="50vp"/>

    <Button
        ohos:id="$+id:async_dispatch_button"
        ohos:height="match_content"
        ohos:width="300vp"
        ohos:background_element="$graphic:button_bg"
        ohos:padding="5vp"
        ohos:text="$string:async_dispatch"
        ohos:text_alignment="center"
        ohos:text_size="18fp"
        ohos:top_margin="10vp"/>

    <Button
        ohos:id="$+id:delay_dispatch_button"
        ohos:height="match_content"
        ohos:width="300vp"
        ohos:background_element="$graphic:button_bg"
        ohos:padding="5vp"
        ohos:text="$string:delay_dispatch"
        ohos:text_alignment="center"
        ohos:text_size="18fp"
        ohos:top_margin="10vp"/>

    <Button
        ohos:id="$+id:group_dispatch_button"
        ohos:height="match_content"
        ohos:width="300vp"
        ohos:background_element="$graphic:button_bg"
        ohos:padding="5vp"
        ohos:text="$string:dispatch_group"
        ohos:text_alignment="center"
        ohos:text_size="18fp"
        ohos:top_margin="10vp"/>

    <Button
        ohos:id="$+id:revoke_task_button"
        ohos:height="match_content"
        ohos:width="300vp"
        ohos:background_element="$graphic:button_bg"
        ohos:padding="5vp"
        ohos:text="$string:revoke_task"
        ohos:text_alignment="center"
        ohos:text_size="18fp"
        ohos:top_margin="10vp"/>

    <Button
        ohos:id="$+id:sync_barrier_button"
        ohos:height="match_content"
        ohos:width="300vp"
        ohos:background_element="$graphic:button_bg"
        ohos:padding="5vp"
        ohos:text="$string:sync_dispatch_barrier"
        ohos:text_alignment="center"
        ohos:text_size="18fp"
        ohos:top_margin="10vp"/>

    <Button
        ohos:id="$+id:async_barrier_button"
        ohos:height="match_content"
        ohos:width="300vp"
        ohos:background_element="$graphic:button_bg"
        ohos:padding="5vp"
        ohos:text="$string:async_dispatch_barrier"
        ohos:text_alignment="center"
        ohos:text_size="18fp"
        ohos:top_margin="10vp"/>

    <Button
        ohos:id="$+id:apply_dispatch_button"
        ohos:height="match_content"
        ohos:width="300vp"
        ohos:background_element="$graphic:button_bg"
        ohos:padding="5vp"
        ohos:text="$string:apply_Dispatch"
        ohos:text_alignment="center"
        ohos:text_size="18fp"
        ohos:top_margin="10vp"/>

    <Text
        ohos:id="$+id:result_text"
        ohos:height="150vp"
        ohos:width="match_parent"
        ohos:background_element="$graphic:common_bg"
        ohos:margin="20vp"
        ohos:multiple_lines="true"
        ohos:padding="10vp"
        ohos:text_size="16fp"/>
</DirectionalLayout>

private void initComponents() {
        Component syncDispatchButton = findComponentById(ResourceTable.Id_sync_dispatch_button);
        Component asyncDispatchButton = findComponentById(ResourceTable.Id_async_dispatch_button);
        Component delayDispatchButton = findComponentById(ResourceTable.Id_delay_dispatch_button);
        Component groupDispatchButton = findComponentById(ResourceTable.Id_group_dispatch_button);
        syncDispatchButton.setClickedListener(this::syncTask);
        asyncDispatchButton.setClickedListener(this::asyncTask);
        delayDispatchButton.setClickedListener(this::delayTask);
        groupDispatchButton.setClickedListener(this::groupTask);
        resultText = (Text) findComponentById(ResourceTable.Id_result_text);
        Component revokeTaskButton = findComponentById(ResourceTable.Id_revoke_task_button);
        Component syncBarrierButton = findComponentById(ResourceTable.Id_sync_barrier_button);
        Component asyncBarrierButton = findComponentById(ResourceTable.Id_async_barrier_button);
        Component applyDispatchButton = findComponentById(ResourceTable.Id_apply_dispatch_button);
        revokeTaskButton.setClickedListener(this::postTaskAndRevoke);
        syncBarrierButton.setClickedListener(this::syncBarrier);
        asyncBarrierButton.setClickedListener(this::asyncBarrier);
        applyDispatchButton.setClickedListener(this::applyDispatchTask);
    }

private void syncTask(Component component) {
        StringBuffer stringBuffer = new StringBuffer();
        TaskDispatcher globalTaskDispatcher = getGlobalTaskDispatcher(TaskPriority.DEFAULT);
        globalTaskDispatcher.syncDispatch(() -> stringBuffer.append("Sync task1 run").append(System.lineSeparator())
        );
        stringBuffer.append("After sync task1").append(System.lineSeparator());
        globalTaskDispatcher.syncDispatch(() -> stringBuffer.append("Sync task2 run").append(System.lineSeparator()));
        stringBuffer.append("After sync task2").append(System.lineSeparator());
        resultText.setText(stringBuffer.toString());
    }

    private void asyncTask(Component component) {
        StringBuffer stringBuffer = new StringBuffer();
        TaskDispatcher globalTaskDispatcher = getGlobalTaskDispatcher(TaskPriority.DEFAULT);
        globalTaskDispatcher.asyncDispatch(() -> {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                HiLog.error(LABEL_LOG, "%{public}s", "AsyncDispatch InterruptedException");
            }
            stringBuffer.append("Async task1 run").append(System.lineSeparator());
            handler.postSyncTask(() -> resultText.setText(stringBuffer.toString()));
        });
        stringBuffer.append("After async task1").append(System.lineSeparator());
        globalTaskDispatcher.asyncDispatch(() -> {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                HiLog.error(LABEL_LOG, "%{public}s", "AsyncDispatch InterruptedException");
            }
            stringBuffer.append("Async task2 run").append(System.lineSeparator());
            handler.postSyncTask(() -> resultText.setText(stringBuffer.toString()));
        });
        stringBuffer.append("After async task2").append(System.lineSeparator());
        resultText.setText(stringBuffer.toString());
    }

    private void delayTask(Component component) {
        StringBuffer stringBuffer = new StringBuffer();
        TaskDispatcher globalTaskDispatcher = getGlobalTaskDispatcher(TaskPriority.DEFAULT);
        final long callTime = System.currentTimeMillis();
        globalTaskDispatcher.delayDispatch(() -> {
            stringBuffer.append("DelayDispatch task1 run").append(System.lineSeparator());
            final long actualDelayMs = System.currentTimeMillis() - callTime;
            stringBuffer.append("ActualDelayTime >= delayTime : ").append((actualDelayMs >= DELAY_TIME));
            handler.postSyncTask(() -> resultText.setText(stringBuffer.toString()));
        }, DELAY_TIME);
        stringBuffer.append("After delayDispatch task1").append(System.lineSeparator());
        resultText.setText(stringBuffer.toString());
    }

    private void groupTask(Component component) {
        StringBuffer stringBuffer = new StringBuffer();
        TaskDispatcher dispatcher = createParallelTaskDispatcher("", TaskPriority.DEFAULT);
        Group group = dispatcher.createDispatchGroup();
        dispatcher.asyncGroupDispatch(group, () -> {
            stringBuffer.append("GroupTask1 is running").append(System.lineSeparator());
            handler.postSyncTask(() -> resultText.setText(stringBuffer.toString()));
        });
        dispatcher.asyncGroupDispatch(group, () -> {
            stringBuffer.append("GroupTask2 is running").append(System.lineSeparator());
            handler.postSyncTask(() -> resultText.setText(stringBuffer.toString()));
        });
        dispatcher.groupDispatchNotify(group, () -> stringBuffer.append(
            "This task running after all tasks in the group are completed").append(System.lineSeparator()));
        resultText.setText(stringBuffer.toString());
    }

    private void postTaskAndRevoke(Component component) {
        StringBuffer stringBuffer = new StringBuffer();
        TaskDispatcher dispatcher = getUITaskDispatcher();
        Revocable revocable = dispatcher.delayDispatch(() -> {
            stringBuffer.append("Delay dispatch").append(System.lineSeparator());
            handler.postSyncTask(() -> resultText.setText(stringBuffer.toString()));
        }, 50);
        boolean revoked = revocable.revoke();
        stringBuffer.append("Revoke result :").append(revoked);
        resultText.setText(stringBuffer.toString());
    }

    private void syncBarrier(Component component) {
        StringBuffer stringBuffer = new StringBuffer();
        TaskDispatcher dispatcher = createParallelTaskDispatcher("SyncBarrierDispatcher", TaskPriority.DEFAULT);
        Group group = dispatcher.createDispatchGroup();
        dispatcher.asyncGroupDispatch(group, () -> stringBuffer.append("Task1 is running").append(System.lineSeparator()));
        dispatcher.asyncGroupDispatch(group, () -> stringBuffer.append("Task2 is running").append(System.lineSeparator()));
        dispatcher.syncDispatchBarrier(() -> stringBuffer.append("Barrier").append(System.lineSeparator()));
        stringBuffer.append("After syncDispatchBarrier").append(System.lineSeparator());
        resultText.setText(stringBuffer.toString());
    }

    private void asyncBarrier(Component component) {
        StringBuffer stringBuffer = new StringBuffer();
        TaskDispatcher dispatcher = createParallelTaskDispatcher("AsyncBarrierDispatcher", TaskPriority.DEFAULT);
        Group group = dispatcher.createDispatchGroup();
        dispatcher.asyncGroupDispatch(group, () -> {
            stringBuffer.append("Task1 is running").append(System.lineSeparator());
            handler.postSyncTask(() -> resultText.setText(stringBuffer.toString()));
        });
        dispatcher.asyncGroupDispatch(group, () -> {
            stringBuffer.append("Task2 is running").append(System.lineSeparator());
            handler.postSyncTask(() -> resultText.setText(stringBuffer.toString()));
        });
        dispatcher.asyncDispatchBarrier(() -> {
            stringBuffer.append("Barrier").append(System.lineSeparator());
            handler.postSyncTask(() -> resultText.setText(stringBuffer.toString()));
        });
        stringBuffer.append("After asyncDispatchBarrier").append(System.lineSeparator());
        resultText.setText(stringBuffer.toString());
    }

    private void applyDispatchTask(Component component) {
        StringBuilder stringBuilder = new StringBuilder();
        final CountDownLatch latch = new CountDownLatch(TASK_TOTAL);
        final ArrayList<Long> indexList = new ArrayList<>(TASK_TOTAL);
        TaskDispatcher globalTaskDispatcher = getGlobalTaskDispatcher(TaskPriority.DEFAULT);
        globalTaskDispatcher.applyDispatch(index -> {
            indexList.add(index);
            latch.countDown();
        }, TASK_TOTAL);
        try {
            latch.await();
        } catch (InterruptedException exception) {
            HiLog.error(LABEL_LOG, "%{public}s", "applyDispatchTask InterruptedException");
        }
        stringBuilder.append("List size matches :").append((indexList.size() == TASK_TOTAL));
        resultText.setText(stringBuilder.toString());
    }

### 鸿蒙 OS Worker 线程更新 UI 的方法 在鸿蒙操作系统中,Worker 是种用于执行长时间运行的任务而不阻塞主线程的机制。由于 Worker 运行在个独立的工作线程上,因此它无法直接访问或修改 UI 组件。为了实现从 Worker 线程向 UI 发送消息并更新界面的效果,通常采用以下几种方式: #### 使用 Emitter 实现线程间通信 Emitter 提供了种发布/订阅模式的消息传递机制,允许不同线程之间发送和接收消息。可以在 Worker 中触发事件,在主线程监听这些事件来间接达到更新 UI 的目的。 ```typescript // 主线程代码片段 import emitter from '@ohos.event.emitter'; emitter.on('updateUI', (data) => { console.info(`Received data: ${JSON.stringify(data)}`); // 执行具体的UI更新逻辑 }); // Worker线程中的代码片段 export default function MyWorker() { let worker = new Worker(); worker.postMessage({ action: 'doSomething', payload: {} }); worker.onmessage = (event) => { const resultData = event.data; // 向主线程发出信号以请求刷新UI emitter.emit('updateUI', { message: "Update your UI here", ...resultData }); }; } ``` 此段代码展示了如何利用 `@ohos.event.emitter` 模块完成跨线程的数据交换[^1]。 #### 利用 AbilitySlice 上下文对象的方法调用 如果是在特定的应用场景比如Ability环境下工作,则可以直接借助AbilitySlice提供的接口来进行UI交互。例如,可以通过 abilityContext.runOnUIThread 来安排任务在UI线程上同步执行。 ```javascript abilityContext.runOnUiThread(() -> { // 在这里放置需要在线程中立即执行的操作 }); ``` 需要注意的是这种方法仅适用于某些特殊情况下,并不是通用解决方案[^3]。 #### 注意事项 - 创建过多的 Workers 可能会引起性能问题以及资源浪费;自 API 版本 9 起,当超过最大允许数目的时候将会引发初始化失败异常而不是简单的拒绝创建新的实例[^4]。 - 尽量减少不必要的线程切换次数,因为频繁地在这两者之间转换可能会带来额外开销影响程序效率。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值