科特林suspend
函数应按照惯例(1)进行非阻塞。通常,我们有依赖Java线程中断机制的旧Java代码,而我们不能(不想)modif(2):
public void doSomething(String arg) {
for (int i = 0; i < 100_000; i++) {
heavyCrunch(arg, i);
if (Thread.interrupted()) {
// We've been interrupted: no more crunching.
return;
}
}
}
修改此代码以在协程中使用的最佳方法是什么?
版本A :这是不可接受的,因为它将在调用者线程上运行代码。因此将违反“暂停功能不会阻止调用者线程” 约定:
suspend fun doSomething(param: String) = delegate.performBlockingCode(param)
版本B :更好,因为它将在后台线程中运行阻止功能,因此它不会阻止调用者线程(除非偶然的情况是调用者使用了Dispatchers中的同一线程。线程池)。但是协程作业的取消不会中断依赖线程中断的performBlockingCode()。
suspend fun doSomething(param: String) = withContext(Dispatchers.Default) {
delegate.performBlockingCode(param)
}
版本C :目前是我认为使其生效的唯一方法。这个想法是使用Java机制将阻塞函数转换为非阻塞,然后使用suspendCancellableCoroutine
(3)将异步方法转换为暂停函数:
private ExecutorService executor = Executors.newSingleThreadExecutor();
public Future doSomethingAsync(String arg) {
return executor.submit(() -> {
doSomething(arg);
});
}
suspend fun doSomething(param: String) = suspendCancellableCoroutine<Any> { cont ->
try {
val future = delegate.doSomethingAsync(param)
} catch (e: InterruptedException) {
throw CancellationException()
}
cont.invokeOnCancellation { future.cancel(true) }
}
如下所述,以上代码将无法正常工作,因为未调用continuation.resumeWith()
版本D :使用CompletableFuture:提供了一种在完成完成时注册回调的方法: thenAccept
private ExecutorService executor = Executors.newSingleThreadExecutor();
public CompletableFuture doSomethingAsync(String arg) {
return CompletableFuture.runAsync(() -> doSomething(arg), executor);
}
suspend fun doSomething(param: String) = suspendCancellableCoroutine<Any> { cont ->
try {
val completableFuture = delegate.doSomethingAsync(param)
completableFuture.thenAccept { cont.resumeWith(Result.success(it)) }
cont.invokeOnCancellation { completableFuture.cancel(true) }
} catch (e: InterruptedException) {
throw CancellationException()
}
}
您知道更好的方法吗?
答案 0 :(得分:1)
您可以通过suspend fun kotlinx.coroutines.runInterruptible
它禁止了编译警告,并且阻塞代码将在取消时抛出InterruptedException
val job = launch {
runInterruptible {
Thread.sleep(500)
}
}
job.cancelAndJoin() // Cause will be 'java.lang.InterruptedException'
经过org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.4.2