什么是协程
协程: 是一种更为灵活高效的"用户线程",能够选择异步还是同步执行,指定运行的线程。
异步、同步编程 : 是指的协程能够选择自身的启动模式,在当前线程堵塞式运行,还是在后台线程异步执行;
指定运行线程:能够方便的选择执行的线程是后台线程还是UI主线程;
在并发处理上会比使用线程来得更加的高效。
进程、线程、协程关系
进程 > 线程 > 协程, 即一个进程可以包含多个线程,一个线程上面可以运行多个协程。
启动方式
目前从非协程环境中启动协程环境主要有三种方式
启动方式 | 说明 |
---|---|
runBlocking | 创建新的协程,运行在当前线程上,所以会堵塞当前线程,直到协程体结束 |
GlobalScope.launch | 启动一个新的线程,在新线程上创建运行协程,不堵塞当前线程 |
GlobalScope.asyn | 启动一个新的线程,在新线程上创建运行协程,并且不堵塞当前线程,支持 通过await获取返回值 |
runBlocking
创建新的协程运行在当前线程上,所以会堵塞当前线程,直到协程体结束
适用范围
用于启动一个协程任务,通常只用于启动最外层的协程,例如线程环境切换到协程环境
示例
/**
* runBlocking创建新的协程运行在当前线程上,所以会堵塞当前线程,直到协程体结束
*
* 适用范围: 用于启动一个协程任务,通常只用于启动最外层的协程,例如线程环境切换到协程环境。
*
* 打印出:
* current thread = main,1
* runBlocking thread = main @coroutine#1,1
* runBlocking end
* current thread end
*/
@Test
fun runBlockingTest() {
println("current thread = ${Thread.currentThread().name},${Thread.currentThread().id}")
//runBlocking运行在当前线程上,堵塞当前线程
runBlocking {
println("runBlocking thread = ${Thread.currentThread().name},${Thread.currentThread().id}")
delay(1000)
println("runBlocking end")
}
//等待runBlocking协程体内的内容执行完毕,才继续执行
println("current thread end")
}
GlobalScope.launch
创建新的协程,默认运行在后台新的线程中,并且不堵塞当前线程
适用范围
适用范围: 需要启动异步线程处理的情况
示例
/**
* GlobalScope.launch默认运行在后台新的调度线程中,并且不堵塞当前线程
*
* 适用范围: 需要启动异步线程处理的情况
*
* 输出:
* current thread = main, 1
* current thread end
* launch thread = DefaultDispatcher-worker-2 @coroutine#1, 12
* launch thread end
*/
@Test
fun launchTest() {
println("current thread = ${Thread.currentThread().name}, ${Thread.currentThread().id}")
//launch启动后台调度线程,并且不堵塞当前线程
GlobalScope.launch {
println("launch thread = ${Thread.currentThread().name}, ${Thread.currentThread().id}")
delay(1000)
println("launch thread end")
}
println("current thread end")
//当前线程休眠以便调度线程有机会执行
Thread.sleep(3000)
}
GlobalScope.async
创建新的协程,默认运行在后台新的线程中,并且不堵塞当前线程,支持通过await获取返回值
GlobalScope.async与GlobalScope.launch大致相同,
区别: 1.async返回类型为Deferred, launch返回类型为job 2.async可以在协程体中自定义返回值,并且通过Deferred.await堵塞当前线程等待接收async协程返回的类型。
适用范围
特别是需要启动异步线程处理并等待处理结果返回的场景
示例
/**
* async与launch的相同点:都是不堵塞当前线程并启动后台调度线程。
* 区别: 1.async返回类型为Deferred, launch返回类型为job
* 2.async可以在协程体中存在自定义的返回值,并且通过Deferred.await堵塞当前线程等待接收async协程返回的类型。
*
* 适用范围: 特别是需要启动异步线程处理并等待处理结果返回的场景
*
* 打印出:
* current thread = main @coroutine#1, 1
* current thread end
* async thread = DefaultDispatcher-worker-1 @coroutine#2, 11
* async end
* result = 123
*/
@Test
fun asyncTest() {
runBlocking {
println("current thread = ${Thread.currentThread().name}, ${Thread.currentThread().id}")
//launch启动后台调度线程,并且不堵塞当前线程
val deferred = GlobalScope.async {
println("async thread = ${Thread.currentThread().name}, ${Thread.currentThread().id}")
delay(1000)
println("async end")
//需要通过标签的方式返回
return@async "123"
}
println("current thread end")
val result = deferred.await()
println("result = $result")
//当前线程休眠以便调度线程有机会执行
Thread.sleep(3000)
}
}
启动方式
目前从非协程环境中启动协程环境主要有三种方式
启动方式 | 说明 |
---|---|
runBlocking | 创建新的协程,运行在当前线程上,所以会堵塞当前线程,直到协程体结束 |
GlobalScope.launch | 启动一个新的线程,在新线程上创建运行协程,不堵塞当前线程 |
GlobalScope.asyn | 启动一个新的线程,在新线程上创建运行协程,并且不堵塞当前线程,支持 通过await获取返回值 |
runBlocking
创建新的协程运行在当前线程上,所以会堵塞当前线程,直到协程体结束
适用范围
用于启动一个协程任务,通常只用于启动最外层的协程,例如线程环境切换到协程环境
示例
/**
* runBlocking创建新的协程运行在当前线程上,所以会堵塞当前线程,直到协程体结束
*
* 适用范围: 用于启动一个协程任务,通常只用于启动最外层的协程,例如线程环境切换到协程环境。
*
* 打印出:
* current thread = main,1
* runBlocking thread = main @coroutine#1,1
* runBlocking end
* current thread end
*/
@Test
fun runBlockingTest() {
println("current thread = ${Thread.currentThread().name},${Thread.currentThread().id}")
//runBlocking运行在当前线程上,堵塞当前线程
runBlocking {
println("runBlocking thread = ${Thread.currentThread().name},${Thread.currentThread().id}")
delay(1000)
println("runBlocking end")
}
//等待runBlocking协程体内的内容执行完毕,才继续执行
println("current thread end")
}
GlobalScope.launch
创建新的协程,默认运行在后台新的线程中,并且不堵塞当前线程
适用范围
适用范围: 需要启动异步线程处理的情况
示例
/**
* GlobalScope.launch默认运行在后台新的调度线程中,并且不堵塞当前线程
*
* 适用范围: 需要启动异步线程处理的情况
*
* 输出:
* current thread = main, 1
* current thread end
* launch thread = DefaultDispatcher-worker-2 @coroutine#1, 12
* launch thread end
*/
@Test
fun launchTest() {
println("current thread = ${Thread.currentThread().name}, ${Thread.currentThread().id}")
//launch启动后台调度线程,并且不堵塞当前线程
GlobalScope.launch {
println("launch thread = ${Thread.currentThread().name}, ${Thread.currentThread().id}")
delay(1000)
println("launch thread end")
}
println("current thread end")
//当前线程休眠以便调度线程有机会执行
Thread.sleep(3000)
}
GlobalScope.async
创建新的协程,默认运行在后台新的线程中,并且不堵塞当前线程,支持通过await获取返回值
GlobalScope.async与GlobalScope.launch大致相同,
区别: 1.async返回类型为Deferred, launch返回类型为job 2.async可以在协程体中自定义返回值,并且通过Deferred.await堵塞当前线程等待接收async协程返回的类型。
适用范围
特别是需要启动异步线程处理并等待处理结果返回的场景
示例
/**
* async与launch的相同点:都是不堵塞当前线程并启动后台调度线程。
* 区别: 1.async返回类型为Deferred, launch返回类型为job
* 2.async可以在协程体中存在自定义的返回值,并且通过Deferred.await堵塞当前线程等待接收async协程返回的类型。
*
* 适用范围: 特别是需要启动异步线程处理并等待处理结果返回的场景
*
* 打印出:
* current thread = main @coroutine#1, 1
* current thread end
* async thread = DefaultDispatcher-worker-1 @coroutine#2, 11
* async end
* result = 123
*/
@Test
fun asyncTest() {
runBlocking {
println("current thread = ${Thread.currentThread().name}, ${Thread.currentThread().id}")
//launch启动后台调度线程,并且不堵塞当前线程
val deferred = GlobalScope.async {
println("async thread = ${Thread.currentThread().name}, ${Thread.currentThread().id}")
delay(1000)
println("async end")
//需要通过标签的方式返回
return@async "123"
}
println("current thread end")
val result = deferred.await()
println("result = $result")
//当前线程休眠以便调度线程有机会执行
Thread.sleep(3000)
}
}