一、关于协程库的导入
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