Versions/v1.2.0-alpha.06/中文

访问线程

Sections3
On This Page3
API Symbols6

访问线程

使用 `Future<T>` 等待线程结束并获取返回值

在上面的例子中,新创建的线程会由于主线程结束而提前结束,在缺乏顺序保证的情况下,甚至可能会出现新创建的线程还来不及得到执行就退出了。可以通过 spawn 表达式的返回值,来等待线程执行结束。

spawn 表达式的返回类型是 Future,其中 T 是类型变元,其类型与 lambda 表达式的返回类型一致。当调用 Futureget() 成员函数时,它将等待它的线程执行完成。Future 的原型声明如下:

下方示例代码演示了如何使用 Futuremain 中等待新创建的线程执行完成:

调用 Future 实例的 get() 会阻塞当前运行的线程,直到 Future 实例所代表的线程运行结束。因此,上方示例有可能会输出类似如下内容:

主线程在完成打印后会因为调用 get() 而等待新创建的线程执行结束。但主线程和新线程的打印顺序具有不确定性。

如果将 fut.get() 移动到主线程的打印之前,如下所示:

主线程将等待新创建的线程执行完成,然后再执行打印,因此程序的输出将变得确定,如下所示:

可见,get() 的调用位置会影响线程是否能同时运行。

Future 除了可以用于阻塞等待线程执行结束以外,还可以获取线程执行的结果。如下是它提供的具体成员函数:

- get(): T:阻塞等待线程执行结束,并返回执行结果,如果该线程已经结束,则直接返回执行结果。

示例代码如下:

输出结果如下:

- get(timeout: Duration): T:阻塞等待该 Future 所代表的线程执行结束,并返回执行结果,当到达超时时间 timeout 时,如果该线程还没有执行结束,将会抛出异常 TimeoutException。如果 timeout <= Duration.Zero, 其行为与 get() 相同。

示例代码如下:

输出结果如下:

cangjie
public class Future<T> {
    // Blocking the current thread, waiting for the result of the thread corresponding to the current Future object.
    // If an exception occurs in the corresponding thread, the method will throw the exception.
    public func get(): T

    // Blocking the current thread, waiting for the result of the thread corresponding to the current Future object.
    // If the corresponding thread has not completed execution within Duration, the method will throws TimeoutException.
    // If `timeout` <= Duration.Zero, its behavior is the same as `get()`.
    public func get(timeout: Duration): T

    // Non-blocking method that immediately returns Option<T>.None if thread has not finished execution.
    // Returns the computed result otherwise.
    // If an exception occurs in the corresponding thread, the method will throw the exception.
    public func tryGet(): Option<T>
}
cangjie
main(): Int64 {
    let fut: Future<Unit> = spawn { =>
        println("New thread before sleeping")
        sleep(100 * Duration.millisecond) // sleep for 100ms.
        println("New thread after sleeping")
    }

    println("Main thread")

    fut.get() // wait for the thread to finish.
    return 0
}
text
New thread before sleeping
Main thread
New thread after sleeping
cangjie
main(): Int64 {
    let fut: Future<Unit> = spawn { =>
        println("New thread before sleeping")
        sleep(100 * Duration.millisecond) // sleep for 100ms.
        println("New thread after sleeping")
    }

    fut.get() // wait for the thread to finish.

    println("Main thread")
    return 0
}
text
New thread before sleeping
New thread after sleeping
Main thread

访问线程属性

每个 Future 对象都有一个对应的仓颉线程,以 Thread 对象为表示。Thread 类主要被用于访问线程的属性信息,例如线程标识等。需要注意的是,Thread 无法直接被实例化构造对象,仅能从 Futurethread 成员属性获取对应的 Thread 对象,或是通过 Thread 的静态成员属性 currentThread 得到当前正在执行线程对应的 Thread 对象。

Thread 类的部分方法定义如下(完整的方法描述可参考《仓颉编程语言库 API》)。

下列示例代码在创建新线程后分别通过两种方式获取线程标识。由于主线程和新线程获取的是同一个 Thread 对象,所以他们能够打印出相同的线程标识。

输出结果如下(其中线程 id 会变化,也可能为其他值):

cangjie
class Thread {
    // Get the currently running thread
    static prop currentThread: Thread

    // Get the unique identifier (represented as an integer) of the thread object
    prop id: Int64

    // Check whether the thread has any cancellation request
    prop hasPendingCancellation: Bool
}
cangjie
main(): Unit {
    let fut = spawn {
        println("Current thread id: ${Thread.currentThread.id}")
    }
    println("New thread id: ${fut.thread.id}")
    fut.get()
}
text
New thread id: 1
Current thread id: 1