Accessing Threads
Inspect one language lane at a time so line-level text and code deltas stay readable.
Diff Lane
English
0 modified sections0 code block delta0 anchor delta
Diff Lane
中文
2 modified sections0 code block delta0 anchor delta
modified使用 `Future<T>` 等待线程结束并获取返回值text+1 line
v1.0.5
Section Text
1
在上面的例子中,新创建的线程会由于主线程结束而提前结束,在缺乏顺序保证的情况下,甚至可能会出现新创建的线程还来不及得到执行就退出了。可以通过 `spawn` 表达式的返回值,来等待线程执行结束。2
3
`spawn` 表达式的返回类型是 `Future<T>`,其中 `T` 是类型变元,其类型与 lambda 表达式的返回类型一致。当调用 `Future<T>` 的 `get()` 成员函数时,它将等待它的线程执行完成。4
5
`Future<T>` 的原型声明如下:6
7
8
下方示例代码演示了如何使用 `Future<T>` 在 `main` 中等待新创建的线程执行完成:9
10
<!-- run -->11
12
13
调用 `Future<T>` 实例的 `get()` 会阻塞当前运行的线程,直到 `Future<T>` 实例所代表的线程运行结束。因此,上方示例有可能会输出类似如下内容:14
15
16
主线程在完成打印后会因为调用 `get()` 而等待新创建的线程执行结束。但主线程和新线程的打印顺序具有不确定性。17
18
如果将 `fut.get()` 移动到主线程的打印之前,如下所示:19
20
<!-- verify -->21
22
23
主线程将等待新创建的线程执行完成,然后再执行打印,因此程序的输出将变得确定,如下所示:24
25
26
可见,`get()` 的调用位置会影响线程是否能同时运行。27
28
`Future<T>` 除了可以用于阻塞等待线程执行结束以外,还可以获取线程执行的结果。如下是它提供的具体成员函数:29
30
- `get(): T`:阻塞等待线程执行结束,并返回执行结果,如果该线程已经结束,则直接返回执行结果。31
32
示例代码如下:33
34
<!-- verify -->35
36
```cangjie37
main(): Int64 {38
let fut: Future<Int64> = spawn {39
sleep(Duration.second) // sleep for 1s.40
return 141
}42
43
try {44
// wait for the thread to finish, and get the result.45
let res: Int64 = fut.get()46
println("result = ${res}")47
} catch (_) {48
println("oops")49
}50
return 051
}52
```53
54
输出结果如下:55
56
```text57
result = 158
```59
60
- `get(timeout: Duration): T`:阻塞等待该 `Future<T>` 所代表的线程执行结束,并返回执行结果,当到达超时时间 timeout 时,如果该线程还没有执行结束,将会抛出异常 TimeoutException。如果 `timeout <= Duration.Zero`, 其行为与 `get()` 相同。61
62
示例代码如下:63
64
<!-- verify -->65
66
```cangjie67
main(): Int64 {68
let fut = spawn {69
sleep(Duration.second) // sleep for 1s.70
return 171
}72
73
// wait for the thread to finish, but only for 1ms.74
try {75
let res = fut.get(Duration.millisecond * 1)76
println("result: ${res}")77
} catch (_: TimeoutException) {78
println("oops")79
}80
return 081
}82
83
```84
85
输出结果如下:86
87
```text88
oops89
```Code 1 · cangjie
1
public class Future<T> {2
// Blocking the current thread, waiting for the result of the thread corresponding to the current Future object.3
// If an exception occurs in the corresponding thread, the method will throw the exception.4
public func get(): T5
6
// Blocking the current thread, waiting for the result of the thread corresponding to the current Future object.7
// If the corresponding thread has not completed execution within Duration, the method will throws TimeoutException.8
// If `timeout` <= Duration.Zero, its behavior is the same as `get()`.9
public func get(timeout: Duration): T10
11
// Non-blocking method that immediately returns Option<T>.None if thread has not finished execution.12
// Returns the computed result otherwise.13
// If an exception occurs in the corresponding thread, the method will throw the exception.14
public func tryGet(): Option<T>15
}Code 2 · cangjie
1
main(): Int64 {2
let fut: Future<Unit> = spawn { =>3
println("New thread before sleeping")4
sleep(100 * Duration.millisecond) // sleep for 100ms.5
println("New thread after sleeping")6
}7
8
println("Main thread")9
10
fut.get() // wait for the thread to finish.11
return 012
}Code 3 · text
1
New thread before sleeping2
Main thread3
New thread after sleepingCode 4 · cangjie
1
main(): Int64 {2
let fut: Future<Unit> = spawn { =>3
println("New thread before sleeping")4
sleep(100 * Duration.millisecond) // sleep for 100ms.5
println("New thread after sleeping")6
}7
8
fut.get() // wait for the thread to finish.9
10
println("Main thread")11
return 012
}Code 5 · text
1
New thread before sleeping2
New thread after sleeping3
Main threadv1.1.0
Section Text
1
在上面的例子中,新创建的线程会由于主线程结束而提前结束,在缺乏顺序保证的情况下,甚至可能会出现新创建的线程还来不及得到执行就退出了。可以通过 `spawn` 表达式的返回值,来等待线程执行结束。2
3
`spawn` 表达式的返回类型是 `Future<T>`,其中 `T` 是类型变元,其类型与 lambda 表达式的返回类型一致。当调用 `Future<T>` 的 `get()` 成员函数时,它将等待它的线程执行完成。4
5
`Future<T>` 的原型声明如下:6
7
<!-- code_no_check -->8
9
下方示例代码演示了如何使用 `Future<T>` 在 `main` 中等待新创建的线程执行完成:10
11
<!-- run -->12
13
14
调用 `Future<T>` 实例的 `get()` 会阻塞当前运行的线程,直到 `Future<T>` 实例所代表的线程运行结束。因此,上方示例有可能会输出类似如下内容:15
16
17
主线程在完成打印后会因为调用 `get()` 而等待新创建的线程执行结束。但主线程和新线程的打印顺序具有不确定性。18
19
如果将 `fut.get()` 移动到主线程的打印之前,如下所示:20
21
<!-- verify -->22
23
24
主线程将等待新创建的线程执行完成,然后再执行打印,因此程序的输出将变得确定,如下所示:25
26
27
可见,`get()` 的调用位置会影响线程是否能同时运行。28
29
`Future<T>` 除了可以用于阻塞等待线程执行结束以外,还可以获取线程执行的结果。如下是它提供的具体成员函数:30
31
- `get(): T`:阻塞等待线程执行结束,并返回执行结果,如果该线程已经结束,则直接返回执行结果。32
33
示例代码如下:34
35
<!-- verify -->36
37
```cangjie38
main(): Int64 {39
let fut: Future<Int64> = spawn {40
sleep(Duration.second) // sleep for 1s.41
return 142
}43
44
try {45
// wait for the thread to finish, and get the result.46
let res: Int64 = fut.get()47
println("result = ${res}")48
} catch (_) {49
println("oops")50
}51
return 052
}53
```54
55
输出结果如下:56
57
```text58
result = 159
```60
61
- `get(timeout: Duration): T`:阻塞等待该 `Future<T>` 所代表的线程执行结束,并返回执行结果,当到达超时时间 timeout 时,如果该线程还没有执行结束,将会抛出异常 TimeoutException。如果 `timeout <= Duration.Zero`, 其行为与 `get()` 相同。62
63
示例代码如下:64
65
<!-- verify -->66
67
```cangjie68
main(): Int64 {69
let fut = spawn {70
sleep(Duration.second) // sleep for 1s.71
return 172
}73
74
// wait for the thread to finish, but only for 1ms.75
try {76
let res = fut.get(Duration.millisecond * 1)77
println("result: ${res}")78
} catch (_: TimeoutException) {79
println("oops")80
}81
return 082
}83
84
```85
86
输出结果如下:87
88
```text89
oops90
```Code 1 · cangjie
1
public class Future<T> {2
// Blocking the current thread, waiting for the result of the thread corresponding to the current Future object.3
// If an exception occurs in the corresponding thread, the method will throw the exception.4
public func get(): T5
6
// Blocking the current thread, waiting for the result of the thread corresponding to the current Future object.7
// If the corresponding thread has not completed execution within Duration, the method will throws TimeoutException.8
// If `timeout` <= Duration.Zero, its behavior is the same as `get()`.9
public func get(timeout: Duration): T10
11
// Non-blocking method that immediately returns Option<T>.None if thread has not finished execution.12
// Returns the computed result otherwise.13
// If an exception occurs in the corresponding thread, the method will throw the exception.14
public func tryGet(): Option<T>15
}Code 2 · cangjie
1
main(): Int64 {2
let fut: Future<Unit> = spawn { =>3
println("New thread before sleeping")4
sleep(100 * Duration.millisecond) // sleep for 100ms.5
println("New thread after sleeping")6
}7
8
println("Main thread")9
10
fut.get() // wait for the thread to finish.11
return 012
}Code 3 · text
1
New thread before sleeping2
Main thread3
New thread after sleepingCode 4 · cangjie
1
main(): Int64 {2
let fut: Future<Unit> = spawn { =>3
println("New thread before sleeping")4
sleep(100 * Duration.millisecond) // sleep for 100ms.5
println("New thread after sleeping")6
}7
8
fut.get() // wait for the thread to finish.9
10
println("Main thread")11
return 012
}Code 5 · text
1
New thread before sleeping2
New thread after sleeping3
Main threadmodified访问线程属性text+1 line
v1.0.5
Section Text
1
每个 `Future<T>` 对象都有一个对应的仓颉线程,以 `Thread` 对象为表示。`Thread` 类主要被用于访问线程的属性信息,例如线程标识等。需要注意的是,`Thread` 无法直接被实例化构造对象,仅能从 `Future<T>` 的 `thread` 成员属性获取对应的 `Thread` 对象,或是通过 `Thread` 的静态成员属性 `currentThread` 得到当前正在执行线程对应的 `Thread` 对象。2
3
`Thread` 类的部分方法定义如下(完整的方法描述可参考《仓颉编程语言库 API》)。4
5
6
下列示例代码在创建新线程后分别通过两种方式获取线程标识。由于主线程和新线程获取的是同一个 `Thread` 对象,所以他们能够打印出相同的线程标识。7
8
<!-- run -->9
10
11
输出结果如下(其中线程 id 会变化,也可能为其他值):Code 1 · cangjie
1
class Thread {2
// Get the currently running thread3
static prop currentThread: Thread4
5
// Get the unique identifier (represented as an integer) of the thread object6
prop id: Int647
8
// Check whether the thread has any cancellation request9
prop hasPendingCancellation: Bool10
}Code 2 · cangjie
1
main(): Unit {2
let fut = spawn {3
println("Current thread id: ${Thread.currentThread.id}")4
}5
println("New thread id: ${fut.thread.id}")6
fut.get()7
}Code 3 · text
1
New thread id: 12
Current thread id: 1v1.1.0
Section Text
1
每个 `Future<T>` 对象都有一个对应的仓颉线程,以 `Thread` 对象为表示。`Thread` 类主要被用于访问线程的属性信息,例如线程标识等。需要注意的是,`Thread` 无法直接被实例化构造对象,仅能从 `Future<T>` 的 `thread` 成员属性获取对应的 `Thread` 对象,或是通过 `Thread` 的静态成员属性 `currentThread` 得到当前正在执行线程对应的 `Thread` 对象。2
3
`Thread` 类的部分方法定义如下(完整的方法描述可参考《仓颉编程语言库 API》)。4
5
<!-- code_no_check -->6
7
下列示例代码在创建新线程后分别通过两种方式获取线程标识。由于主线程和新线程获取的是同一个 `Thread` 对象,所以他们能够打印出相同的线程标识。8
9
<!-- run -->10
11
12
输出结果如下(其中线程 id 会变化,也可能为其他值):Code 1 · cangjie
1
class Thread {2
// Get the currently running thread3
static prop currentThread: Thread4
5
// Get the unique identifier (represented as an integer) of the thread object6
prop id: Int647
8
// Check whether the thread has any cancellation request9
prop hasPendingCancellation: Bool10
}Code 2 · cangjie
1
main(): Unit {2
let fut = spawn {3
println("Current thread id: ${Thread.currentThread.id}")4
}5
println("New thread id: ${fut.thread.id}")6
fut.get()7
}Code 3 · text
1
New thread id: 12
Current thread id: 1