Kotlin之协程初探

433 阅读1分钟

协程是一种线程框架,它运行在线程上,每个协程就是一个耗时任务,协程内部程序是按顺序执行,它是一种非阻塞式的,用户可以手动控制协程的挂起和运行;

官方介绍: 协程通过将复杂性放入库来简化异步编程。程序的逻辑可以在协程中顺序地表达,而底层库会为我们解决其异步性。该库可以将用户代码的相关部分包装为回调、订阅相关事件、在不同线程(甚至不同机器)上调度执行,而代码则保持如同顺序执行一样简单;

引入

kotlin{
    experimental {
        coroutines 'enable'
    }
}
// 协程
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1'

创建协程

GlobalScope.launch {
    for(i in 1..3){
    println("协程任务1打印: $i")
    }
    delay(200)
    for(i in 1..3){
    println("协程任务2打印: $i")
    }
}
for(i in 1..3){
    println("主线程打印: $i")
}

可以通过日志看到协程是按照顺序执行:

2020-05-26 15:30:58.673 24381-24381/? I/System.out: 主线程打印: 1
2020-05-26 15:30:58.673 24381-24381/? I/System.out: 主线程打印: 2
2020-05-26 15:30:58.673 24381-24381/? I/System.out: 主线程打印: 3
2020-05-26 15:30:58.674 24381-24446/? I/System.out: 协程任务1打印: 1
2020-05-26 15:30:58.674 24381-24446/? I/System.out: 协程任务1打印: 2
2020-05-26 15:30:58.674 24381-24446/? I/System.out: 协程任务1打印: 3
2020-05-26 15:30:58.878 24381-24448/? I/System.out: 协程任务2打印: 1
2020-05-26 15:30:58.878 24381-24448/? I/System.out: 协程任务2打印: 2
2020-05-26 15:30:58.878 24381-24448/? I/System.out: 协程任务2打印: 3

源码


public fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job {
    val newContext = newCoroutineContext(context)
    val coroutine = if (start.isLazy)
    LazyStandaloneCoroutine(newContext, block) else
    StandaloneCoroutine(newContext, active = true)
    coroutine.start(start, coroutine, block)
    return coroutine
}

CoroutineStart: 启动模式,默认就是DEFAULT,即创建协程就启动,还有一个LAZY,懒加载模式,需要调用start才会启动;

  • DEFAULT:默认模式,立即启动协程;
  • ATOMIC:
  • UNDISPATCHED:
  • LAZY:懒加载模式,需要的时候,再启动;

block: 闭包方法体,定义协程内需要执行的操作;

Job: 创建协程的返回值,可以把job当做协程对象本身;

  • start():启动协程;
  • join():等待协程执行完毕;
  • cancel():取消一个协程包含内部的子协程,但是async修饰的协程如果已开始则没法取消;

Suspend: 用来修饰协程的方法,被修饰的方法可以被协程挂起,suspend修饰的方法只能被suspend修饰的方法调用;

GlobalScope.async: async和launch的区别就是async有返回值

GlobalScope.launch(Dispatchers.IO){
    // 多协程间 suspend函数运行
    val suspend2 = GlobalScope.async(Dispatchers.IO){
        return@async suspend2()
    }
    println("hello ${suspend2.isActive}")
    println("hello ${suspend2.isActive} ${suspend2.await()}")
    println("hello ${suspend2.isActive}")
//  println("hello $suspend1 $suspend2 thread:${Thread.currentThread().name}")
}

打印结果

2020-05-26 19:23:42.426 9411-9485/? I/System.out: hello true
2020-05-26 19:23:42.427 9411-9487/? I/System.out: hello suspend2 start, thread:DefaultDispatcher-worker-3
2020-05-26 19:23:42.441 9411-9485/? I/System.out: hello suspend2 end, thread:DefaultDispatcher-worker-1
2020-05-26 19:23:42.442 9411-9485/? I/System.out: hello true suspend2
2020-05-26 19:23:42.442 9411-9485/? I/System.out: hello false