一、关于协程库的导入

1、使用下载包的方式

可以到该网站下载https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core对应的协程库

本地调试运行可以使用类似命令:kotlinc -classpath kotlinx-coroutines-core-1.2.2.jar -script coroutine.kts

 

2、使用gradle的方式

在build.gradle的dependencies中添加

implementation “org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.2”

 

二、关于协程的使用

1、基础的语法

import kotlinx.coroutines.*

fun task1() {
    println("start task1 in Thread ${Thread.currentThread()}")
    println("end task1 in Thread ${Thread.currentThread()}")
}
fun task2() {
    println("start task2 in Thread ${Thread.currentThread()}")
    println("end task2 in Thread ${Thread.currentThread()}")
}
println("start")
runBlocking {
    task1()
    task2()
    println("call task1 and task2 in Thread ${Thread.currentThread()}")
}

如上所示,在runBlocking中运行,假设当前的kts文件下面有一个对应的kotlinx-coroutines-core-1.2.2.jar,那么可以使用如下的命令运行

kotlinc -classpath kotlinx-coroutines-core-1.2.2.jar -script coroutine.kts

运行的结果为

start
start task1 in Thread Thread[main,5,main]
end task1 in Thread Thread[main,5,main]
start task2 in Thread Thread[main,5,main]
end task2 in Thread Thread[main,5,main]
call task1 and task2 in Thread Thread[main,5,main]

这个流程基本跟咱们顺序调用的一样,没看出协程的特点

如果我们的runBlocking使用如下那么可以看出一点区别

runBlocking {
    launch {task1()}
    launch {task2()}
    println("call task1 and task2 in Thread ${Thread.currentThread()}")
}

结果如下
call task1 and task2 in Thread Thread[main,5,main]
start task1 in Thread Thread[main,5,main]
end task1 in Thread Thread[main,5,main]
start task2 in Thread Thread[main,5,main]  
end task2 in Thread Thread[main,5,main]

可以看出使用launch进行调用,结果有一些不一样,如上黄底的结果先打印出来,再打印task1和task2

 

2、使用delay和yield为另外的刮起任务提供执行机会

注意:kotlin只允许带有suspend关键字的函数使用挂起点,所以使用delay和yield的时候,该函数需要标注suspend

import kotlinx.coroutines.*
suspend fun task1() {
    println("start task1 in Thread ${Thread.currentThread()}")
    yield()
    println("end task1 in Thread ${Thread.currentThread()}")
}
suspend fun task2() {
    println("start task2 in Thread ${Thread.currentThread()}")
    yield()
    println("end task2 in Thread ${Thread.currentThread()}")
}
println("start")
runBlocking {
    launch {task1()}
    launch {task2()}
    println("call task1 and task2 in Thread ${Thread.currentThread()}")
}

如上所示因为task1和task2中包含yield函数,所以函数需要使用如上黄底的标志;上面的执行结果为

start
call task1 and task2 in Thread Thread[main,5,main]
start task1 in Thread Thread[main,5,main]
start task2 in Thread Thread[main,5,main]
end task1 in Thread Thread[main,5,main]
end task2 in Thread Thread[main,5,main]

 

3、显示设置上下文

在第二点中,虽然跑的都是多线程,但是我们发现他们都是在主线程中执行(同一个线程)

我们可以指定在哪个函数中运行

runBlocking {
    launch(Dispatchers.Default) {task1()}
    launch {task2()}
    println("call task1 and task2 in Thread ${Thread.currentThread()}")
}

如上所示,task1在不同的线程中运行,运行结果如下所示

start
start task1 in Thread Thread[DefaultDispatcher-worker-1,5,main]
end task1 in Thread Thread[DefaultDispatcher-worker-1,5,main]
call task1 and task2 in Thread Thread[main,5,main]
start task2 in Thread Thread[main,5,main]
end task2 in Thread Thread[main,5,main]

 

可以使用指定的线程池中的线程创建执行器

Executors.newSingleThreadExecutor().asCoroutineDispatcher().use {context ->
    println("start")
    runBlocking {
        launch(context) {task1()}
        launch {task2()}

        println("called task1 and task2 from Thread ${Thread.currentThread()}")
    }
}

1、创建执行器:Executors.newSingleThreadExecutor(); 需要导入包:import java.util.concurrent.Executors

2、使用kotlinx.coroutines库添加asCoroutineDispatcher() 从而获得一个CoroutineContext, 最后调用context

如上的显示结果

start
start task1 in Thread Thread[pool-1-thread-1,5,main]
end task1 in Thread Thread[pool-1-thread-1,5,main]
called task1 and task2 from Thread Thread[main,5,main]
start task2 in Thread Thread[main,5,main]
end task2 in Thread Thread[main,5,main]

 

 

4、在挂起点切换线程

使用CoroutineContext和CoroutineStart参数来实现

launch有两个参数,第一个context是当前在那个context中运行,第二个start是该launch的运行机制

context:如果不设置,则在当前的线程中运行,如果有指定的context则在指定context中运行

start有

DEFAULT, ATOMIC, UNDISPATCHED,LAZY

DEFAULT:我们如果start不设置则默认为该参数,即在当前的上下文中运行

ATOMIC:如果该函数不允许被取消

LAZY:懒操作,使用该参数则会在遇到调用start才会开始运行:launch是start,async则是join或者await

UNDISPATCHED:刚开始使用当前的上下文中进行,如果遇到挂起点之后则会切换到其他线程:这个比较特殊,是实验性,则需要标注对应的实验性

Executors.newSingleThreadExecutor().asCoroutineDispatcher().use {context ->
    println("start")
    runBlocking {
        @OptIn(ExperimentalCoroutinesApi::class)
        launch(context = context, start = CoroutineStart.UNDISPATCHED) {task1()}
        launch {task2()}
        println("called task1 and task2 from Thread ${Thread.currentThread()}")
    }
}

如上的黄色标记所示,并且执行运行的时候要做特殊的标记-opt-in=kotlin.RequiresOptIn

整体运行命令:

kotlinc -opt-in=kotlin.RequiresOptIn -classpath kotlinx-coroutines-core-1.2.2.jar -script coroutine.kts

 

5、使用指定的上下文运行

runBlocking {
    println("starting in Thread ${Thread.currentThread()}")
    withContext(Dispatchers.Default) {task1()}
    launch{task2()}
    println("ending in Thread ${Thread.currentThread()}")
}

注意withContext没有启动新的协程,只是修改了当前执行的协程的上下文;运行结果如下所示

starting in Thread Thread[main,5,main]
start task1 in Thread Thread[DefaultDispatcher-worker-2,5,main]
end task1 in Thread Thread[DefaultDispatcher-worker-2,5,main]
ending in Thread Thread[main,5,main]
start task2 in Thread Thread[main,5,main]
end task2 in Thread Thread[main,5,main]

 

原文地址:http://www.cnblogs.com/czwlinux/p/16910228.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性