Vik*_*rya 1 kotlin kotlin-coroutines
fun main() = runBlocking {
var i = 1
var job = launch (Dispatchers.Default){
println("Thread name = ${Thread.currentThread().name}")
while (i < 10) { // replace i < 10 to isActive to make coroutine cancellable
delay(500L)
// runBlocking { delay(500L) }
println("$isActive ${i++}")
}
}
println("Thread name = ${Thread.currentThread().name}")
delay(2000L) // delay a bit
println("main: I'm tired of waiting!")
job.cancelAndJoin() // cancels the job and waits for its completion
println("main: Now I can quit.")
}
Run Code Online (Sandbox Code Playgroud)
输出
Thread name = main
Thread name = DefaultDispatcher-worker-1
true 1
true 2
true 3
main: I'm tired of waiting!
main: Now I can quit.
Run Code Online (Sandbox Code Playgroud)
如果我使用runBlocking { delay(500L) }那么上面的协同例程是不可取消的。因此,它将打印直到 的所有值9。
但是当我delay(500L)自动使用时,协同例程可以被取消。为什么 ?
delay实际上它自己并没有做任何事情,它只是安排协程在稍后的时间点恢复。当然,可以随时取消延续。
runBlocking另一方面,实际上阻塞了一个线程(这就是为什么编译器会抱怨协程内的阻塞操作,以及为什么你永远不runBlocking应该在单元测试之外使用)。
注意:由于main现在可以是挂起函数,因此通常不需要在核心应用程序代码中使用它。
不应在协程
runBlocking中使用此函数
协程与线程一样,并不是真正可中断的;它们必须依赖于协作取消(另请参阅为什么停止线程不好)。这意味着取消实际上也不会执行任何操作;当您取消上下文时,它只是通知其所有子上下文自行取消,但仍在运行的任何代码将继续运行,直到达到取消检查为止。
重要的是要认识到这runBlocking 不是一个suspend函数。它无法暂停、恢复或取消。默认情况下,父上下文不会传递给它(它接收一个EmptyCoroutineContext),因此用于执行 的协程runBlocking不会对上游发生的任何事情做出反应。
当你写的时候
while (i < 10) {
runBlocking { delay(500L) }
println("$isActive ${i++}")
}
Run Code Online (Sandbox Code Playgroud)
这里没有可取消的操作。因此,代码从不检查其上下文是否已被取消,因此它将继续执行直到完成。
delay但是,是可以取消的;一旦其父上下文被取消,它就会立即恢复并抛出异常(即停止。)
看一下生成的代码:
@Nullable
public final Object invokeSuspend(@NotNull Object $result) {
switch (this.label) {
case 0:
while (i.element < 10) {
BuildersKt.runBlocking$default( ... );
...
System.out.println(var3);
}
return Unit.INSTANCE;
default:
throw new IllegalStateException( ... );
}
}
Run Code Online (Sandbox Code Playgroud)
对比一下这个
while (i.element < 10) {
BuildersKt.runBlocking$default( ... );
...
System.out.println(var3);
}
Run Code Online (Sandbox Code Playgroud)
和
do {
...
System.out.println(var3);
if (i.element >= 10) {
return Unit.INSTANCE;
}
...
} while (DelayKt.delay(500L, this) != var5);
Run Code Online (Sandbox Code Playgroud)
为了简洁起见,省略了变量声明和参数 ( ...)。
runBlocking如果当前线程被中断,则会提前终止,但这又是完全相同的协作机制,只不过它在线程级别而不是协程上运行。
| 归档时间: |
|
| 查看次数: |
2220 次 |
| 最近记录: |