一般我们需要异步操作的时候,都是通过多线程来实现的,但是线程的创建和开启是个耗性能的操作,开少量的线程没有问题,可是线程多了就有问题了,而且线程还会有各种数据同步的问题。
协程作为一个轻量级的线程,可以完美解决这些问题。你试下开100万个线程?不死机我吃电脑。但是你开100万个协程,那是分分钟的事。
这里只说android
和kotlin
中的使用。
// kotlin 版本
ext.kotlin_version = '1.3.41'
// repository
jcenter()
// 依赖
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0-RC2'
fun main() {
GlobalScope.launch {
println("我是一个协程")
delay(1000)
println("我不会打印,因为主线程已经退出了")
}
// 和上面的代码并行执行
Thread.sleep(500)
println("主线程退出了")
}
输出:
我是一个协程
主线程退出了
fun main() {
runBlocking {
launch {
println("协程开始")
delay(1000)
println("协程结束")
}
}
// 会阻塞等待 runBlocking 中的代码执行完毕
Thread.sleep(500)
println("主线程退出了")
}
输出:
协程开始
协程结束
主线程退出了
fun main() {
runBlocking {
println("开始")
launch {
test()
}
println("结束")
}
}
suspend fun test() {
delay(1000L)
println("我是suspend方法打印的")
}
输出:
开始
结束
我是suspend方法打印的
fun main() {
runBlocking {
println("开始")
val job = launch {
delay(1000L)
println("in launch")
}
job.join()
println("结束")
}
}
输出:
开始
in launch
结束
Job.cancel 实际上是抛出异常,会直接中断执行。
fun main() {
runBlocking {
println("开始")
val job = launch {
try {
var i = 1
while (isActive) {
print(i++)
delay(500L)
}
} finally {
println("\n异常退出")
}
}
delay(1300L)
job.cancelAndJoin()// cancel实质上是抛出异常,所以会直接停止,而不会等到delay完后再停止
println("结束")
}
}
输出:
开始
123
异常退出
结束
Timeout
实际上也是抛出异常。
fun main() {
runBlocking {
println("开始")
try {
val result = withTimeout(1300) {
repeat(10) {
print(it)
delay(500)
}
"正常完成,没有Timeout"
}
println("\n结束 result=$result")
} catch (e: TimeoutCancellationException) {
println("\n结束 Timeout了")
}
}
}
输出:
开始
012
结束 Timeout了
Channel
相当于BlockingQueue
fun main() {
runBlocking {
println("开始")
val channel = Channel<Int>()
launch {
for (x in 1..5) channel.send(x * x)
channel.close()
}
for (y in channel) print("$y ")
println("\n结束")
}
}
输出:
开始
1 4 9 16 25
结束
fun main() {
runBlocking {
println("开始")
val d = async {
println("async start...")
delay(1000)
println("async end")
999
}
println("d=${d.await()}")
println("结束")
}
}
如果想要 async
不自行执行,加上 CoroutineStart.LAZY
即可,然后 async
将会等待调用 start
或者 await
后才会执行,如下:
fun main() {
runBlocking {
println("开始")
val d = async(start = CoroutineStart.LAZY) {
println("async start...")
delay(1000)
println("async end")
999
}
d.start()
println("d=${d.await()}")
println("结束")
}
}
输出:
开始
async start…
async end
d=999
结束
fun main() {
runBlocking {
// 默认执行在当前线程
launch {
println("launch\t\t\t\t\t" + Thread.currentThread().name)
}
// 默认执行在工作线程
GlobalScope.launch {
println("GlobalScope.launch\t\t" + Thread.currentThread().name)
}
// 默认执行在工作线程
launch(Dispatchers.Default) {
println("Dispatchers.Default\t\t" + Thread.currentThread().name)
}
// 默认执行在工作线程
launch(Dispatchers.IO) {
println("Dispatchers.IO\t\t\t" + Thread.currentThread().name)
}
// 不限制的,可能执行在任何线程,甚至里面的不同行代码也会执行在不同的线程
launch(Dispatchers.Unconfined) {
println("Dispatchers.Unconfined\t" + Thread.currentThread().name)
}
// 只有android中才能用main
// launch(Dispatchers.Main) {
// println("Dispatchers.Main\t\t" + Thread.currentThread().name)
// }
}
}
输出:
GlobalScope.launch DefaultDispatcher-worker-1
Dispatchers.Default DefaultDispatcher-worker-3
Dispatchers.IO DefaultDispatcher-worker-3
Dispatchers.Unconfined main
launch main
https://kotlinlang.org/docs/reference/coroutines/coroutines-guide.html
https://github.com/Kotlin/kotlinx.coroutines