kotlin是协程的一种实现
-
Dispatchers.IO
:适用于执行磁盘或网络 I/O 操作的调度器,例如文件读写、网络请求等。在 Android 中,Dispatchers.IO
会使用一个专门的线程池来处理这些操作,以防止阻塞主线程。 -
Dispatchers.Main
:适用于处理与 UI 相关的操作的调度器,例如更新 UI 界面、响应用户输入等。在 Android 中,Dispatchers.Main
通常会将协程切换到主线程执行,确保 UI 操作在主线程中进行。 -
Dispatchers.Unconfined
:不对协程的执行环境做任何限制,使用该调度器时,协程将在调用它的线程中执行,直到遇到挂起函数为止,之后会在恢复执行时继续在之前的线程中执行。 -
Dispatchers.Default
:适用于执行 CPU 密集型任务的调度器,例如算法计算、数据处理等。Dispatchers.Default
在 Android 中会使用一个共享的线程池来处理这些任务,以便在多个协程之间进行合理的调度。
Kotlin
package com.tiger.kotlincoroutine.coroutine
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
fun main() {
//IO线程 超大密集的计算 Default
/**
* IO
* Default
* Main
*
*/
CoroutineScope(Dispatchers.IO).launch {
test()
// withContext(Dispatchers.Main){
//
// }
}
println("主线程")
Thread.sleep(2000)
}
/**
* 协程代码块
*/
suspend fun test() {
println("协程开始")
delay(1000)
println("协程结束")
}
1.runBlocking
Kotlin
package com.tiger.kotlincoroutine.coroutine
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
fun main() {
println("hello")
//如果给的参数第一个为空,那么它会去找到这个协程外面调用它的这个线程 一般在写Test的时候才用一下 阻塞式协程
val i = runBlocking (Dispatchers.IO){
//如果制定了了调度器,它会被分配到另一个线程上面执行 ,但也可以阻塞当前线程
println(
Thread.currentThread().name
)
//这个协程会阻塞当前线程 同步执行
delay(2000)
1
}
println(
Thread.currentThread().name
)
println("world $i ")
}
Kotlin
package com.tiger.kotlincoroutine.coroutine
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
fun main() {
println("hello")
//如果给的参数第一个为空,那么它会去找到这个协程外面调用它调度器 一般在写Test的时候才用一下 阻塞式协程
//会等里面所有的协程执行完了,才会释放主线程
val i = runBlocking (Dispatchers.IO){
//如果制定了了调度器,它会被分配到另一个线程上面执行 ,但也可以阻塞当前线程
println(
Thread.currentThread().name
)
println(this)
//this :BlockingCoroutine 可以再次开启一个协程
val job = this.launch {
//这个开启的协程不会阻塞当前线程,异步
println(
//没有指定 ,他会默认继承上面所在的调度器 被这个调度器管理的线程池的线程去执行
Thread.currentThread().name
)
delay(5200)
}
println(job.isActive)
println(job.cancel())
println(job.isActive)
println("延迟了吗")
//这个协程会阻塞当前线程 同步执行
delay(2000)
1
}
println(
Thread.currentThread().name
)
println("world $i ")
/**
* 总结
* IO 网络请求 数据库
* default 密集型数据处理操作 数据计算
* main UI操作
*
*/
}
Kotlin
package com.tiger.kotlincoroutine.coroutine
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
fun main() {
println("hello")
val i = runBlocking (Dispatchers.IO){
request{
//手动切换到UI线程里
withContext(Dispatchers.Main){
//修改UI
}
}
}
println("world $i")
}
suspend fun request(finish:suspend ()->Unit){
delay(3000)
println("网络请求成功")
finish()
}
好处:不会出现在其他的线程里出现UI报错的问题了
2.GlobalScope
Kotlin
package com.tiger.kotlincoroutine.coroutine
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
fun main() {
val launch = GlobalScope.launch { //全局指的是整个程序的生命周期 就算Activity销毁了这个GlobalScope还是存在的
// 这样可能会造成一些奇怪的问题
delay(3000)
println("hello")
}//这不是阻塞当前线程的一个协程操作
val launch1 = GlobalScope.launch {
}
println(launch===launch1)
//不能调用cancel 方法,因为作用域是整个生命周期的,不能由我们来管理
while (true);
}
3.CoroutineScope
Kotlin
package com.tiger.kotlincoroutine.coroutine
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
fun main() {
//推荐使用这个 不是全局的
val coroutineScope1 = CoroutineScope(Dispatchers.Default)
coroutineScope1.launch {
delay(3000)
println("结束")
}
coroutineScope1.launch {
delay(3000)
println("结束")
}
coroutineScope1.cancel() //可以手动进行取消,不会涉及到全局 整个程序的生命周期
Thread.sleep(4000)
println("主线程结束")
}
4.Launch分析
4.1 第一个参数 context: CoroutineContext
Kotlin
package com.tiger.kotlincoroutine.coroutine
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.newCoroutineContext
import kotlinx.coroutines.runBlocking
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
@OptIn(ExperimentalStdlibApi::class)
fun main() {
val runBlocking = runBlocking {
val launch = this.launch(Dispatchers.Default) {
println(this.coroutineContext.get(CoroutineDispatcher).toString())//拿到调度器信息
}
println(launch)
launch
}//是同一个对象
println(runBlocking)
}
Kotlin
package com.tiger.kotlincoroutine.coroutine
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.newCoroutineContext
import kotlinx.coroutines.runBlocking
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
@OptIn(ExperimentalStdlibApi::class)
fun main() {
val runBlocking = runBlocking(Dispatchers.IO) {
val launch = this.launch (Dispatchers.Default){
println(this.coroutineContext.get(CoroutineDispatcher).toString())//拿到调度器信息
}
println(launch)
launch
}//是同一个对象
println(runBlocking)
}
4.2 第二个参数 start:CoroutineStart
- default 是协程默认的启动方式 由默认协程调度去调度 决定在哪一个线程上面执行
Kotlin
val runBlocking = runBlocking(Dispatchers.IO) {
val launch = this.launch{
println("hello")
delay(1000)
println("end")
}
//异步就会走到下面,end不执行
launch.cancel()
}//是同一个对象
- ATOMIC
Kotlin
val runBlocking = runBlocking(Dispatchers.IO) {
val launch = this.launch(start = CoroutineStart.ATOMIC){//ATOMIC是一个立即启动的过程 把执行此协程的优先级调上去
println("hello")
delay(1000)
println("end")
}
//异步就会走到下面,end不执行
launch.cancel()
}//是同一个对象
3.LAZY 可以自己控制何时启动
Kotlin
val runBlocking = runBlocking(Dispatchers.IO) {
val launch = this.launch(start = CoroutineStart.LAZY){//LAZY 可以自己控制何时启动
println("hello")
delay(1000)
println("end")
}
println("先打印,在启动")
//异步就会走到下面,end不执行
launch.start()
}//是同一个对象
5. async详解
Kotlin
this.async(Dispatchers.Default, start = CoroutineStart.DEFAULT){
println("进来异步了")
delay(1000)
println("被卡住了")
}
1.获取值方法1
Kotlin
package com.tiger.kotlincoroutine.coroutine
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
fun main() {
val coroutineScope = CoroutineScope(Dispatchers.Default)
val async = coroutineScope.async(Dispatchers.Default, start = CoroutineStart.DEFAULT) {
println("进来异步了")
delay(1000)
println("被卡住了")
"协程异步返回值"
}
Thread.sleep(3000)
val completed = async.getCompleted()
println(completed)
}
Kotlin
package com.tiger.kotlincoroutine.coroutine
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
fun main() {
runBlocking {
val async = this.async {
test1()
}
for (i in 0..10) {
println("hello $i")
}
val await = async.await()
println(await)
}
}
suspend fun test1():Int{
println("执行中")
delay(3000)
return 100
}
6.select函数 与 onAwait方法
Kotlin
package com.tiger.kotlincoroutine.coroutine
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.selects.select
fun main() {
runBlocking {
val d = this.async {
delay(2000)
test1(1)
}//同时启动的
val c = this.async {
test1(2)
}//同时启动的
//泛型是协程返回的类型
//select可以等待多个协程的结束
//select会阻塞当前的线程
println(select<String> {
c.onAwait.invoke {
"c" //it是协程返回值
}
d.onAwait.invoke {
"d"
}
//谁先执行结束就返回谁
})
println("end")
}
}
suspend fun test1(item:Int):Int{
println("执行中$item")
delay(3000)
return 100
}
7. withContenxt
Kotlin
package com.tiger.kotlincoroutine.coroutine
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
@OptIn(ExperimentalStdlibApi::class)
fun main() {
runBlocking(Dispatchers.IO) {
println(coroutineContext.get(CoroutineDispatcher).toString())
val withContext = withContext(Dispatchers.Default) {
//会对协程有一个阻塞 挂起就是阻塞的意思
delay(2000)
println(coroutineContext.get(CoroutineDispatcher).toString())
//返回值就是lamda最后一行 ,并且结束以后会回到之前的那个协程上面继续执行
"withContext result"
}
println(withContext)
println(coroutineContext.get(CoroutineDispatcher).toString())
}
}
Kotlin
package com.tiger.kotlincoroutine.coroutine
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
@OptIn(ExperimentalStdlibApi::class)
fun main() {
//如果不想阻塞当前协程,那就重新开一个
runBlocking(Dispatchers.IO) {
println(coroutineContext.get(CoroutineDispatcher).toString())
launch {
val withContext = withContext(Dispatchers.Default) {
//会对协程有一个阻塞 挂起就是阻塞的意思
delay(2000)
println(coroutineContext.get(CoroutineDispatcher).toString())
//返回值就是lamda最后一行 ,并且结束以后会回到之前的那个协程上面继续执行
"withContext result"
}
println(withContext)
}
println(coroutineContext.get(CoroutineDispatcher).toString())
}
}
8.suspend关键字
协程就是任务代码块,有调度器进行线程分配执行此代码块,可以公用一个线程,异步执行代码块,也可以不是一个线程执行.
suspend 声明一个挂起函数,可以阻塞当前协程去执行代码块里的内容,主要是针对协程的。
因为 Thread.sleep 是停止线程的,协程是在线程上面跑的。
delay是延迟当前协程,不停线程,其他协程在此线程上面跑的话,那么都会被停止