kotlin练习 - 协程

kotlin练习 - 协程

GlobalScope构造函数

  • launch : 创建协程
  • async : 创建带返回值的协程,返回 Deferred
  • withContext : 不会创建新的协程,在指定协程上运行代码块
  • runBlocking : 不是GlobalScope的API,可以单独使用, runBlocking里面的delay()会堵塞当前线程,launch等不会堵塞
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
fun main(arg: Array<String>) {
GlobalScope.launch(Dispatchers.Main) {
LogUtils.d("当前线程main: ${Thread.currentThread().name} ")
withContextTest()
}
//newSingleThreadContext 单线程
//newFixedThreadPoolContext 线程池
val singleThreadContext = newSingleThreadContext("single")
GlobalScope.launch(singleThreadContext) {
LogUtils.d("当前线程_单线程: ${Thread.currentThread().name} ")//single
}
val fixedThreadPoolContext = newFixedThreadPoolContext(1, "fixed")
GlobalScope.launch(fixedThreadPoolContext) {
LogUtils.d("当前线程_线程池: ${Thread.currentThread().name} ")//fixed
}
}

suspend fun withContextTest() {
withContext(Dispatchers.IO) {
LogUtils.d("当前线程io: ${Thread.currentThread().name} ")
}
}

CoroutineContext协程运行的线程调度器

  • Dispatchers.Default : 默认(如果不写,默认就是Dispatchers.Default模式)
  • Dispatchers.IO : IO线程
  • Dispatchers.Main : 主线程
  • Dispatchers.Unconfined : 没指定,就是在当前线程

CoroutineStart 启动模式

  • CoroutineStart.DEFAULT:默认(如果不写,默认就是CoroutineStart.DEFAULT模式)
  • CoroutineStart.ATOMIC:自动(协程在开始执行之前不能被取消)
  • CoroutineStart.UNDISPATCHED:立即执行协程
  • CoroutineStart.LAZY:懒加载

Job方法

  • job.start() : 启动协程,除了 lazy 模式,协程都不需要手动启动

  • job.join() : 等待协程执行完毕后再执行后面的代码块

  • job.cancel() : 取消一个协程
    协程的取消有些特质,因为协程内部可以在创建协程的,这样的协程组织关系可以称为父协程,子协程:

    1. 父协程手动调用 cancel() 或者异常结束,会立即取消它的所有子协程
    2. 父协程必须等待所有子协程完成(处于完成或者取消状态)才能完成
    3. 子协程抛出未捕获的异常时,默认情况下会取消其父协程
  • job.cancelAndJoin() : 等待协程取消完毕后再执行后面的代码块

  • job.isActive : true - 处于活动状态

  • job.isCancelled : true - 已完成

  • job.isCompleted : true - 已取消

第一个协程程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

fun main(arg: Array<String>) {
GlobalScope.launch {//在后台启动一个新的协程并继续
delay(2000L)//非阻塞的等待 2 秒钟(默认时间单位是毫秒)
println("我是kotlin")
}
println("你好,")//协程已在等待时主线程还在继续
Thread.sleep(3000L)// 阻塞主线程 3 秒钟来保证 JVM 存活
}
println("运行了吗?")
}

桥接阻塞与非阻塞的世界

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

import kotlinx.coroutines.*

fun main(arg: Array<String>) {
GlobalScope.launch {
//在后台启动新的协程并继续
delay(2000L)//非阻塞的等待 2 秒钟(默认时间单位是毫秒)
println("当前线程: ${Thread.currentThread().name} ,我是kotlin")
}
println("当前线程: ${Thread.currentThread().name} ,你好,")//协程已在等待时主线程还在继续
runBlocking {
//主线程
delay(3000L)//延迟 3 秒来保证 JVM 的存活
println("当前线程: ${Thread.currentThread().name} ,运行了吗?")
}
}
1
2
3
4
5
6
7
8
9
10
11
12
import kotlinx.coroutines.*

fun main() = runBlocking<Unit> {
//启动主协程
GlobalScope.launch {
delay(2000L)//非阻塞的等待 2 秒钟(默认时间单位是毫秒)
println("当前线程: ${Thread.currentThread().name} ,我是kotlin")
}
println("当前线程: ${Thread.currentThread().name} ,你好,")//主协同程序在此处继续
delay(3000L)// //延迟 3 秒以保持JVM活动
println("当前线程: ${Thread.currentThread().name} ,运行了吗?")
}

等待工作

1
2
3
4
5
6
7
8
9
10
11
12
13

import kotlinx.coroutines.*

fun main() = runBlocking {

var job = GlobalScope.launch {
delay(2000L)//非阻塞的等待 2 秒钟(默认时间单位是毫秒)
println("当前线程: ${Thread.currentThread().name} ,我是kotlin")
}
println("当前线程: ${Thread.currentThread().name} ,你好,")//主协同程序在此处继续
job.join()//等到子协程完成后进行
println("当前线程: ${Thread.currentThread().name} ,运行了吗?")
}

结构化的并发

1
2
3
4
5
6
7
8
9
10

import kotlinx.coroutines.*

fun main() = runBlocking {
launch {
delay(2000L)//非阻塞的等待 2 秒钟(默认时间单位是毫秒)
println("当前线程: ${Thread.currentThread().name} ,我是kotlin")
}
println("当前线程: ${Thread.currentThread().name} ,你好,")//主协同程序在此处继续
}

范围构建器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

import kotlinx.coroutines.*

fun main() = runBlocking {
launch {
delay(200L)
println("当前线程: ${Thread.currentThread().name} ,我是Kotlin")
}
coroutineScope {
launch {
delay(500L)
println("当前线程: ${Thread.currentThread().name} ,你知道吗")
}
delay(100L)
println("当前线程: ${Thread.currentThread().name} ,运行了吗")
}
println("当前线程: ${Thread.currentThread().name} ,你好,")
}

提取函数重构

1
2
3
4
5
6
7
8
9
10
11
12
13
import kotlinx.coroutines.*

fun main() = runBlocking {
launch {
doWorld()
}
println("当前线程: ${Thread.currentThread().name} ,你好,")
}

suspend fun doWorld() {
delay(2000L)
println("当前线程: ${Thread.currentThread().name} ,我是Kotlin")
}

协同程序重量轻

1
2
3
4
5
6
7
8
9
10
import kotlinx.coroutines.*

fun main() = runBlocking {
repeat(100_000){
launch {
delay(1000L)
println(".")
}
}
}

全局协程像守护线程

1
2
3
4
5
6
7
8
9
10
11
12

import kotlinx.coroutines.*

fun main() = runBlocking {
GlobalScope.launch {
repeat(1000) {
println("当前是第${(it + 1)}个线程")
delay(500L)
}
}
delay(1300L)
}

协程请求网络数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
coroutine.setOnClickListener { click() }
}

private fun click() = runBlocking {
GlobalScope.launch(Dispatchers.Main) {
coroutine.text = GlobalScope.async(Dispatchers.IO) {
// 比如进行了网络请求
// 放回了请求后的结构
return@async "main"
}.await()
}
}
}