【华为鸿蒙开发技术】仓颉语言中的使用 Future线程管理与同步

举报
柠檬味拥抱1 发表于 2024/09/28 14:32:04 2024/09/28
【摘要】 仓颉语言中的线程管理与同步:使用 Future<T>在现代编程中,多线程编程是一项重要的技能。仓颉语言通过提供强大的线程管理功能,使得开发者可以方便地创建和管理线程。在这篇文章中,我们将深入探讨如何使用 Future<T> 来等待线程结束并获取返回值,同时还会介绍如何处理线程的属性与取消请求。 使用 Future<T> 等待线程执行在仓颉语言中,创建线程通常使用 spawn 表达式。这个表...

仓颉语言中的线程管理与同步:使用 Future<T>

在现代编程中,多线程编程是一项重要的技能。仓颉语言通过提供强大的线程管理功能,使得开发者可以方便地创建和管理线程。在这篇文章中,我们将深入探讨如何使用 Future<T> 来等待线程结束并获取返回值,同时还会介绍如何处理线程的属性与取消请求。

使用 Future<T> 等待线程执行

在仓颉语言中,创建线程通常使用 spawn 表达式。这个表达式的返回值是一个 Future<T> 对象,其中 T 是线程执行结果的类型。调用 Future<T>get() 方法,可以阻塞当前线程,直到目标线程执行完成,并返回其结果。

示例代码

import std.sync.*
import std.time.*

main(): Int64 {
    let fut: Future<Unit> = spawn { =>
        println("New thread before sleeping")
        sleep(100 * Duration.millisecond) // 睡眠100毫秒
        println("New thread after sleeping")
    }

    println("Main thread")
    fut.get() // 等待线程完成
    return 0
}

在这个示例中,主线程在打印 “Main thread” 后会调用 fut.get(),从而等待新创建的线程执行结束。由于 get() 的调用位置,输出结果可能会是:

New thread before sleeping
Main thread
New thread after sleeping

确定执行顺序

如果我们将 fut.get() 移动到主线程打印之前,程序的输出顺序将变得确定:

import std.sync.*
import std.time.*

main(): Int64 {
    let fut: Future<Unit> = spawn { =>
        println("New thread before sleeping")
        sleep(100 * Duration.millisecond)
        println("New thread after sleeping")
    }

    fut.get() // 等待线程完成
    println("Main thread")
    return 0
}

此时,输出结果将是:

New thread before sleeping
New thread after sleeping
Main thread

获取线程执行结果

除了等待线程完成,Future<T> 还允许获取线程的执行结果。get() 方法会返回线程的结果,如果线程已结束则直接返回结果。

示例代码

import std.sync.*
import std.time.*

main(): Int64 {
    let fut: Future<Int64> = spawn {
        sleep(Duration.second) // 睡眠1秒
        return 1
    }

    try {
        let res: Int64 = fut.get()
        println("result = ${res}")
    } catch (_) {
        println("oops")
    }
    return 0
}

输出结果为:

result = 1

访问线程属性

每个 Future<T> 对象都与一个 Thread 对象相对应,开发者可以通过该对象访问线程的属性,例如线程标识和取消请求状态。

示例代码

main(): Unit {
    let fut = spawn {
        println("Current thread id: ${Thread.currentThread.id}")
    }
    println("New thread id: ${fut.thread.id}")
    fut.get()
}

该示例中,主线程和新线程都可以获取相同的线程标识:

New thread id: 1
Current thread id: 1

终止线程

可以通过 Future<T>cancel() 方法向对应线程发送终止请求。需要注意的是,cancel() 方法并不会立即停止线程执行,而是请求线程自行处理终止逻辑。

示例代码

import std.sync.SyncCounter

main(): Unit {
    let syncCounter = SyncCounter(1)
    let fut = spawn {
        syncCounter.waitUntilZero()
        if (Thread.currentThread.hasPendingCancellation) {
            println("cancelled")
            return
        }
        println("hello")
    }
    fut.cancel()    // 发送取消请求
    syncCounter.dec()
    fut.get() // 等待线程结束
}

运行结果为:

cancelled

错误处理与异常

在多线程编程中,处理线程执行中的异常是非常重要的。仓颉语言的 Future<T> 提供了机制来捕获和处理这些异常。使用 try 块包裹 get() 方法调用,可以确保即使线程内发生了错误,主线程也能优雅地处理这些异常。

示例代码

下面的示例展示了如何处理线程中的异常:

import std.sync.*

main(): Int64 {
    let fut: Future<Int64> = spawn {
        // 故意引发一个异常
        if (true) {
            throw "An error occurred"
        }
        return 42
    }

    try {
        let res: Int64 = fut.get()
        println("Result = ${res}")
    } catch (e) {
        println("Caught an exception: ${e}")
    }
    return 0
}

在这个例子中,线程内故意引发了一个异常。主线程通过 try 块捕获并处理这个异常,输出如下:

Caught an exception: An error occurred

这种机制确保了即使在并发环境中,错误也不会导致程序崩溃,开发者可以对异常进行有效处理。

非阻塞获取结果

除了阻塞式的 get() 方法,Future<T> 还提供了非阻塞的方法 tryGet(),允许开发者立即获取线程执行的结果,而不必等待。

示例代码

下面的代码演示了如何使用 tryGet()

import std.sync.*
import std.time.*

main(): Int64 {
    let fut: Future<Int64> = spawn {
        sleep(Duration.second) // 睡眠1秒
        return 42
    }

    // 尝试立即获取结果
    let res: Option<Int64> = fut.tryGet()
    match (res) {
        case Some(val) => println("Result = ${val}")
        case None => println("Thread is still running.")
    }

    // 睡眠一段时间后再次尝试获取结果
    sleep(Duration.second)
    res = fut.tryGet()
    match (res) {
        case Some(val) => println("Result after waiting = ${val}")
        case None => println("Thread is still running.")
    }

    return 0
}

在这个示例中,第一次调用 tryGet() 可能会返回 None,因为线程尚未完成。然而,在睡眠一秒后再次调用时,结果应该能够返回:

Thread is still running.
Result after waiting = 42

这种方式为开发者提供了灵活性,允许在需要时检查线程状态,而不是始终阻塞。

使用计数器实现线程同步

在多线程编程中,确保多个线程之间的同步是一个常见需求。仓颉语言提供了 SyncCounter 类,可以帮助开发者轻松实现这一点。

示例代码

下面的代码示范了如何使用 SyncCounter 来同步多个线程:

import std.sync.SyncCounter

main(): Unit {
    let counter = SyncCounter(3) // 期望3个线程完成

    for (i in 0..2) {
        spawn {
            println("Thread ${i} is doing work.")
            sleep(500 * Duration.millisecond) // 模拟工作
            counter.dec() // 完成工作后减少计数
        }
    }

    // 等待所有线程完成
    counter.waitUntilZero()
    println("All threads have completed.")
}

在这个例子中,主线程启动了三个子线程,每个线程模拟工作并在完成后减少计数器。当所有线程完成工作后,主线程会打印“所有线程已完成”。

管理线程的生命周期

在复杂的多线程应用中,管理线程的生命周期显得尤为重要。仓颉语言允许开发者通过 Future<T>Thread 类有效控制线程的创建、执行和结束。

示例代码

以下示例展示了如何管理线程的生命周期,并使用 Thread 类访问线程属性:

import std.sync.*

main(): Unit {
    let fut = spawn {
        println("Thread is starting...")
        sleep(Duration.second)
        println("Thread is finishing...")
    }

    println("Main thread is waiting for thread to finish.")
    fut.get() // 等待线程结束

    // 访问线程属性
    let threadId = fut.thread.id
    println("Finished with thread id: ${threadId}")
}

在这个例子中,主线程等待子线程完成,并在结束后打印线程的标识。这种方式使得开发者能够有效跟踪每个线程的执行状态。

线程的优先级与调度

仓颉语言允许开发者为线程设置优先级,以便更好地管理资源和调度。这对于需要高实时性的应用尤为重要。

示例代码

下面的代码演示了如何设置线程优先级:

import std.sync.*

main(): Unit {
    let futHigh = spawn {
        Thread.currentThread.priority = 10 // 设置高优先级
        println("High priority thread running...")
        sleep(500 * Duration.millisecond)
    }

    let futLow = spawn {
        Thread.currentThread.priority = 1 // 设置低优先级
        println("Low priority thread running...")
        sleep(500 * Duration.millisecond)
    }

    futHigh.get()
    futLow.get()
}

在这个示例中,高优先级线程将在低优先级线程之前执行,从而展示了如何使用优先级来影响线程的调度。

以上代码和功能展示了仓颉语言在多线程编程中的强大能力,使得开发者可以灵活、高效地管理和使用线程。

总结

在仓颉语言中,使用 Future<T> 进行多线程编程提供了强大的工具。通过 spawn 创建线程后,可以使用 get() 等方法等待线程完成并获取结果,或使用 tryGet() 非阻塞地检查线程状态。此外,SyncCounter 可以实现线程之间的同步,而线程的优先级设置允许开发者管理资源调度。处理线程中的异常也变得简单,确保程序的稳定性和可靠性。这些特性使得仓颉语言非常适合开发复杂的并发应用。

image.png

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。