首先协程是轻量级的线程
协程创建方式
1.GlobalScope.launch
GlobalScope.launch(Dispatchers.Main) {
println("")
}
这函数创建了一个协程的作用域,Lambda表达式就在协程中运行了,这个函数创建的是一个顶层协程,这种协程当程序运行结束也结束,你会发现执行后日志不会打印,因为还没有来得及执行代码块中的代码执行,程序就结束了。
2.delay
GlobalScope.launch{
println("")
delay(1000)
}
这个时候加一个延时就行了,delay函数是一个非阻塞的挂起函数,delay函数会挂起当前协程,当不会影响其他协程
这里相信大家一定想到了Thread,sleep()函数,但Thread,sleep()函数会阻塞当前线程,这样线程下的所有协程也会被阻塞。
3.runBlocking
runBlocking {
println("")
delay(1000)
}
此函数也创建了一个协程的作用域,但它可以保证协程中所有代码执行完之前一直阻塞当前线程,但只建议测试使用。
4.launch
runBlocking {
launch{
println("")
delay(1000)
}
launch{
println("")
delay(1000)
}
}
此函数只能在协程的作用域中使用,然后再当前协程的作用域下创建子协程,如果外层协程结束,那此作用域下的所有协程都会结束。
5.suspend
suspend fun printDelay() {
println("")
delay(1000)
}
用于将部分代码封装到一个方法中,声明为挂起函数,挂起函数间可以相互调用,但是无法提供协程作用域。
6.coroutineScope
suspend fun printDelay()=coroutineScope {
launch{
println("")
delay(1000)
}
}
首先coroutineScope也是一个挂起函数,而且会继承外部的协程作用域并创建一个子协程,这样我们就解决了上面的问题,而且它和runBlocking一样可以保证协程中所有代码执行完。
7.取消协程
val job=GlobalScope.launch{
println("")
delay(1000)
}
job.cancel()
其实launch函数返回了一个Job对象,调用cancel函数可取消协程。
8.获取返回结果
runBlocking {
println("")
val result=async{
6*2
}.await()
delay(1000)
}
async函数可以创建一个子协程并返回一个Deferred对象,如果想获取aa=sync函数代码块中的执行结果,就调用Deferred对象的await函数,当调用await函数时,如果代码没有执行完,就会阻塞当前协程。
9.并行获取返回结果
runBlocking {
println("")
val result=async{
6*2
}
val result1=async{
6+8
}
Log.i("","result is ${result.await()+result1.await()}")
delay(1000)
}
在最后调用2个async函数的await函数,就变成了并发执行关系。
10.withContext
runBlocking {
val result=withContext(Dispatchers.Default){
6*2
}
delay(1000)
}
类似async函数,会马上执行代码块的代码,同时挂起外部协程。当代码块代码执行完后,会返回最后一行代码作为返回值。
与async函数不同的是,withContext要求强制输入一个线程参数。
这个参数有三个可以选择
(1)Dispatchers.Default
表示默认低并发的线程策略,适合计算密集型的任务
(2)Dispatchers.IO
表示较高并发线程策略,适合执行的代码大多数时间都在阻塞和等待中,比如网络请求
(3)Dispatchers.Main
表示不会开启子线程,而在主线程中执行代码,只能在Android代码中可以使用
11.线程参数
其实除了coroutineScope函数之外,其他函数都可以指定一个线程参数,只是withContext要求强制输入一个线程参数。