基础使用
我们若要使用到 Kotlin 协程,首先需要添加依赖:
dependencies {
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
}
 
然后通过以下代码就可以启动协程:
        CoroutineScope(Dispatchers.Main).launch {
        }
 
这样,就能够在主线程中执行代码了。
调度器
而这个调度器不仅只有 Dispatchers.Main 这种,还有:
- Dispatchers.Main
 - Dispatchers.Unconfined
 - Dispatchers.Default
 - Dispatchers.IO
 
温馨提示:每个调度器里面所写的结论只针对于当前的调度器,并不是针对协程整体来讲
Dispatchers.Main
测试代码:
    val startTime = System.currentTimeMillis()
    println("--1--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
    CoroutineScope(Dispatchers.Main).launch {
        println("--2--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
        Thread.sleep(3000)
        println("--3--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
    }
    println("--4--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
    Thread.sleep(3000)
    println("--5--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
 
输出结果:
I/System.out: --1--main--time:0
I/System.out: --4--main--time:62
I/System.out: --5--main--time:3064
I/System.out: --2--main--time:3095
I/System.out: --3--main--time:6098
 
阶段性结论:
- 协程里面的代码在主线程执行。
 - 协程外的代码和协程内的代码即使都是在主线程中执行,但是,并不会直接顺序执行,而且继续执行下,等某个时刻再执行协程里面的代码。
 - 若协程外的主线程阻塞了,会等主线程阻塞完才会执行协程里面的代码。
 
不过,在这里有个疑问,就是第二点中的某个时刻该怎么理解?
- 它是一定等协程外的代码执行完才会执行协程里面的代码吗?
 - 还是协程外的代码还没完,就会切到协程里面进行执行?
 
在这里,我模拟下在协程外执行一些耗时的操作:
测试代码:
    val startTime = System.currentTimeMillis()
    println("--1--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
    CoroutineScope(Dispatchers.Main).launch {
        println("--2--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
        Thread.sleep(3000)
        println("--3--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
    }
    println("--4--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
//        Thread.sleep(3000)
    for(index in 0..10000000000){}
    println("--5--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
 
输出结果:
I/System.out: --1--main--time:0
I/System.out: --4--main--time:67
I/System.out: --5--main--time:12738
I/System.out: --2--main--time:12765
I/System.out: --3--main--time:15766
 
可以初步理解为:只有协程外部的代码执行完才会执行协程内部的代码
Dispatchers.Main 总结:
- 协程里面的代码在主线程执行。
 - 协程外的代码和协程内的代码即使都是在主线程中执行,但是,并不会直接顺序执行,而且继续执行下去。
 - 若协程外的主线程阻塞了,会等主线程阻塞完才会执行协程里面的代码。
 - 只有协程外部的代码执行完才会执行协程内部的代码
 
Dispatchers.Unconfined
测试代码:
    val startTime = System.currentTimeMillis()
    println("--1--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
    CoroutineScope(Dispatchers.Unconfined).launch {
        println("--2--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
        Thread.sleep(3000)
        println("--3--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
    }
    println("--4--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
    for(index in 0..10000000000){}
    println("--5--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
 
输出结果:
I/System.out: --1--main--time:0
I/System.out: --2--main--time:52
I/System.out: --3--main--time:3053
I/System.out: --4--main--time:3054
I/System.out: --5--main--time:15267
 
阶段性结论:
- 在主线程中执行。
 - 能跟协程外部的代码顺序执行下去。
 
不过这里有一个很明显的问题,既然是顺序执行下去,那么,Dispatchers.Unconfined 还有什么意义?
另外,若外部线程不是主线程,那么,Dispatchers.Unconfined 还会是在主线程执行吗?还会顺序执行吗?
在这里,我尝试在子线程中执行 Dispatchers.Unconfined ,并且在 Dispatchers.Unconfined 中执行挂起操作:
测试代码:
    Thread {
        val startTime = System.currentTimeMillis()
        println("--1--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
        CoroutineScope(Dispatchers.Unconfined).launch {
            println("--2--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
//            Thread.sleep(3000)
            withContext(Dispatchers.IO) {
            }
            println("--3--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
        }
        println("--4--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
        for (index in 0..10000000000) {
        }
        println("--5--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
    }.start()
 
输出结果:
I/System.out: --1--Thread-2--time:0
I/System.out: --2--Thread-2--time:155
I/System.out: --4--Thread-2--time:284
I/System.out: --3--DefaultDispatcher-worker-1--time:286
I/System.out: --5--Thread-2--time:18155
 
阶段性结论:
- Dispatchers.Unconfined 并不是一定会在主线程执行,而是会延续协程外的线程,并通过在遇到挂起操作前顺序执行。
 - Dispatchers.Unconfined 的代码并不是一直在同个线程中执行,在遇到挂起操作之后,会开启新的线程去执行代码。
 
Dispatchers.Unconfined 总结:
- 协程里面的代码在遇到挂起操作之前,会延续协程外的线程进行顺序执行。
 - 在遇到挂起操作之后,会开启新的线程去执行代码。
 
Dispatchers.Default、Dispatchers.IO
测试代码:
     Thread {
        val startTime = System.currentTimeMillis()
        println("--1--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
        CoroutineScope(Dispatchers.Default).launch {
            println("--2--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
//            Thread.sleep(3000)
            withContext(Dispatchers.IO) {
            }
            println("--3--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
        }
        println("--4--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
        for (index in 0..10000000000) {
        }
        println("--5--${Thread.currentThread().name}--time:${System.currentTimeMillis() - startTime}")
    }.start()
 
输出结果:
I/System.out: --1--Thread-2--time:0
I/System.out: --4--Thread-2--time:117
I/System.out: --2--DefaultDispatcher-worker-1--time:120
I/System.out: --3--DefaultDispatcher-worker-1--time:174
I/System.out: --5--Thread-2--time:16104
 
Dispatchers.Default、Dispatchers.IO 总结:
- 协程里面的代码会重新开启一个线程进行执行,非主线程。
 










