看几张图
协程原理
• 可以把耗时任务先挂起
• 等时间到了再从线程池中取出空闲的线程执行
• 但是必须是挂起函数才能挂起
挂起函数
关键字suspend
- 挂起函数:可以被挂起执行 到时间之后从线程池中空闲的线程中恢复执行
- 挂起函数必须通过suspend进行修饰
- 挂起函数必须在协程中执行 或者在其他挂起函数中执行
协程的取消
import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking
fun main(args: Array<String>)= runBlocking {
val job = launch {
(1..10).forEach {
println("打印$it")
delay(500L)
}
}
//定时3秒钟,调用cancel方法取消协程
delay(3000L)
//取消协程
job.cancel()
job.join()
}
输出:
协程的定时任务
import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking
import kotlinx.coroutines.experimental.withTimeout
fun main(args: Array<String>) = runBlocking {
val job = launch {
withTimeout(2000L) {
(1..10).forEach {
println("打印$it")
delay(500L)
}
}
}
job.join()
}
输出:
取消失效
fun main(args: Array<String>) = runBlocking{
val job = launch {
(1..10).forEach {
println("打印$it")
Thread.sleep(500L)
}
}
//定时2秒钟 停止协程
delay(2000L)
//取消协程
job.cancel()//取消挂起 Thread.sleep是阻塞式函数,不是挂起函数
job.join()
}
输出:
协程的状态
import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking
fun main(args: Array<String>)= runBlocking {
val job = launch {
(1..10).forEach {
println("打印$it")
delay(500L)
}
}
//定时3秒钟 停止协程
delay(3000L)
//协程状态
println("取消之前${job.isActive}")
//取消协程
job.cancel()
println("取消之后${job.isActive}")
job.join()
}
输出:
协程的返回值
import kotlinx.coroutines.experimental.async
import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.runBlocking
/**
* 第一中启动协程方式:launch 没有返回值
* 第二种启动协程方式:async 需要返回值就是用async
*/
fun main(args: Array<String>) = runBlocking{
//Deferred 是job的子类
val job1 = async { job1() }
val job2 = async { job2() }
val result1 = job1.await()//执行完协程之后才能获取到数据
val result2 = job2.await()
println(result1)
println(result2)
}
suspend fun job1():String{
println("开始执行job1")
delay(1000L)
println("执行了job1")
return "job1"
}
suspend fun job2():String{
println("开始执行job2")
delay(1000L)
println("执行了job2")
return "job2"
}
输出:
协程的上下文
import kotlinx.coroutines.experimental.*
fun main(args: Array<String>)= runBlocking {
//第一个代表协程上下文 指定协程代码在哪个线程池中运行 默认是通过Commpool实现的
val job1 = launch {
println("协程执行")
}
val job2 = launch(CommonPool) {
println("协程执行")
}
val job3 = launch(Unconfined) {//运行在主线程中
println("协程执行")
}
val job4 = launch(coroutineContext) {//运行在父协程的上下文中 当前运行在主线程中
println("协程执行")
}
val job5 = launch(newFixedThreadPoolContext(5,"新线程")) {//自定义线程池执行
println("协程执行")
}
job1.join()
job2.join()
}
看结果额,很重要
我们以前在使用线程时,线程在执行过程中发送阻塞,再次执行时是在同一个线程,而协程不同,不一定是不是在同一个线程