我们知道kotlin协程的示例代码中多是取消delay,这和java中打断sleep相似。那么对于执行文件读写操作的代码,取消是否能结束线程呢?本篇主要就这一问题进行验证
0. 先说结论
结论是无法结束线程真正达到取消任务的目的
1. 验证代码
import kotlinx.coroutines.*
import java.io.BufferedInputStream
import java.io.File
import java.io.FileInputStream
import kotlin.system.measureTimeMillis
@ExperimentalCoroutinesApi
fun main() = runBlocking{
val job = async(Dispatchers.Default) {
fileReadTest()
println("thread = ${Thread.currentThread()}")
}
delay(1300L)
println("main: I'm tired of waiting!")
// job.cancelAndJoin()
job.cancel()
println("main: Now I can quit.")
println("main: thread = ${Thread.currentThread()}")
}
private suspend fun fileReadTest() {
val dir = System.getProperty("user.dir")
val file = File(dir, "test_file.zip")
println("path = ${file.absolutePath}")
val fileInputStream = FileInputStream(file)
val buffer = ByteArray(1024)
var bos = BufferedInputStream(fileInputStream)
var length = -1
val time = measureTimeMillis {
while (true) {
length = bos.read(buffer)
if (length <= 0) {
break
}
println("readed size = $length")
}
}
println("读取结束, 消耗时间 = $time ms")
}
截取部分日志情况如下
readed size = 1024
readed size = 1024
readed size = 1024
readed size = 1024
readed size = 1024
readed size = 1024
readed size = 1024
readed size = 1024
readed size = 891
读取结束, 消耗时间 = 3050 ms
thread = Thread[DefaultDispatcher-worker-1,5,main]
代码在delay 1300ms的时候调用了cancel()方法,但线程依然执行了3050ms,说明线程并没有在调用取消之后真正被取消掉。说明协程的取消方法无法取消掉io操作,推测网络操作也是一样无法真正取消掉线程调用的。
withContext(NonCancellable): 让挂起函数不被取消里面也得出了结论协程的取消无法取消执行计算任务的线程。
目前看起来,kotlin这一套里面所谓方便的取消机制也仅仅是能取消delay,这点java中也能做到打断sleep。
kotlin的书和官方文档都没有找到io操作的api,还是只能使用java的。从这些来看,kotlin算不上一门独立的语言,只是java的寄生语言,或者是一种java方言。