协程.md

2021-08-11  本文已影响0人  just0119
private fun getTest() {
    Log.d("cjq", "协程初始化开始,时间: " + System.currentTimeMillis())
    GlobalScope.launch(Dispatchers.Unconfined) {
        Log.d("cjq","协程 ${Thread.currentThread()}")
        for (i in 1..3) {
            Log.d("cjq", "协程任务1打印第$i 次,时间: " + System.currentTimeMillis())
        }
        delay(500)
        for (i in 1..3) {
            Log.d("cjq", "协程任务2打印第$i 次,时间: " + System.currentTimeMillis())
        }
    }
    Log.d("cjq","主线程 ${Thread.currentThread()}")
    Thread.sleep(500)
    Log.d("cjq", "主线程运行,时间: " + System.currentTimeMillis())

    for (i in 1..3) {
        Log.d("cjq", "主线程打印第$i 次,时间: " + System.currentTimeMillis())
    }
}
D/cjq: 协程初始化开始,时间: 1626134403936
D/cjq: 主线程 Thread[main,5,main]
D/cjq: 协程 Thread[DefaultDispatcher-worker-1,5,main]
D/cjq: 协程任务1打印第1 次,时间: 1626134404003
D/cjq: 协程任务1打印第2 次,时间: 1626134404003
D/cjq: 协程任务1打印第3 次,时间: 1626134404003
D/cjq: 主线程运行,时间: 1626134404539
D/cjq: 主线程打印第1 次,时间: 1626134404540
D/cjq: 主线程打印第2 次,时间: 1626134404540
D/cjq: 主线程打印第3 次,时间: 1626134404540
D/cjq: 协程任务2打印第1 次,时间: 1626134404552
D/cjq: 协程任务2打印第2 次,时间: 1626134404552
D/cjq: 协程任务2打印第3 次,时间: 1626134404552
public fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job {
    val newContext = newCoroutineContext(context)
    val coroutine = if (start.isLazy)
        LazyStandaloneCoroutine(newContext, block) else
        StandaloneCoroutine(newContext, active = true)
    coroutine.start(start, coroutine, block)
    return coroutine
}

launcher有3个参数和一个返回值job ,第一个参数CoroutineContext 理解为协程的上下文,可设置4种线程模式:
~ Dispatchers.Default 不设置即是Dispatcher.Default
~ Dispatcher.IO
~ Dispatcher.Main
~ Dispatcher.Umconfined 未指定线程,在当前线程
第二个参数CoroutineStart 启动模式
~ Default 默认模式,创建就启动
~ Atomic
~ Undispatched
~ Lazy 懒加载模式,需要时启动

private fun getTest() {
    Log.d("cjq", "协程初始化开始,时间: " + System.currentTimeMillis())
    val job :Job = GlobalScope.launch(start = CoroutineStart.LAZY) {
        Log.d("cjq","协程 ${Thread.currentThread()}")
        for (i in 1..3) {
            Log.d("cjq", "协程任务1打印第$i 次,时间: " + System.currentTimeMillis())
        }
        delay(500)
        for (i in 1..3) {
            Log.d("cjq", "协程任务2打印第$i 次,时间: " + System.currentTimeMillis())
        }
    }
    Log.d("cjq","主线程 ${Thread.currentThread()}")
    Thread.sleep(500)
    Log.d("cjq", "主线程运行,时间: " + System.currentTimeMillis())
    job.start()
    for (i in 1..3) {
        Log.d("cjq", "主线程打印第$i 次,时间: " + System.currentTimeMillis())
    }
}
D/cjq: 协程初始化开始,时间: 1626135267624
D/cjq: 主线程 Thread[main,5,main]
D/cjq: 主线程运行,时间: 1626135268190
D/cjq: 主线程打印第1 次,时间: 1626135268216
D/cjq: 主线程打印第2 次,时间: 1626135268216
D/cjq: 主线程打印第3 次,时间: 1626135268217
D/cjq: 协程 Thread[DefaultDispatcher-worker-1,5,main]
D/cjq: 协程任务1打印第1 次,时间: 1626135268218
D/cjq: 协程任务1打印第2 次,时间: 1626135268218
D/cjq: 协程任务1打印第3 次,时间: 1626135268218
D/cjq: 协程任务2打印第1 次,时间: 1626135268760
D/cjq: 协程任务2打印第2 次,时间: 1626135268760
D/cjq: 协程任务2打印第3 次,时间: 1626135268760

返回值job 理解为协程对象本身
1、 job.start() 启动协程,除了lazy模式,其他都不需要手动启动
2、 job.join() 等待协程执行完毕
3、 job.cancel() 取消协程
4、 job.cancelAndJoin() 等待协程执行完毕后取消

private fun getTest() {
    Log.d("cjq", "协程初始化开始,时间: " + System.currentTimeMillis())
    val job :Job = GlobalScope.launch() {
        Log.d("cjq","协程 ${Thread.currentThread()}")
        val deferred = GlobalScope.async {
            delay(1000)
            Log.d("cjq","协程async ${Thread.currentThread()}")
            return@async "async"
        }
        Log.d("cjq","协程async外 ${Thread.currentThread()}")
       val result = deferred.await()
        Log.d("cjq","协程async返回值 $result")
    }
    Log.d("cjq","主线程 ${Thread.currentThread()}")
}
 D/cjq: 协程初始化开始,时间: 1626136029482
 D/cjq: 主线程 Thread[main,5,main]
 D/cjq: 协程 Thread[DefaultDispatcher-worker-1,5,main]
 D/cjq: 协程async外 Thread[DefaultDispatcher-worker-1,5,main]
 D/cjq: 协程async Thread[DefaultDispatcher-worker-1,5,main]
 D/cjq: 协程async返回值 async

deferred继承Job,并增加了一个方法await,async不会阻塞当前线程,但会阻塞所在协程,也就是挂起。如下比较:

private fun test2() {
    GlobalScope.launch(Dispatchers.IO) {
        Log.d("cjq", "launch : ${Thread.currentThread()}")
        val token = GlobalScope.async {
           return@async getToken()
        }.await()
        Log.d("cjq","token:$token")
        val string = GlobalScope.async {
            return@async getString()
        }.await()
        getBody()

    }
    Log.d("cjq", "out : ${Thread.currentThread()}")
}
suspend fun getToken():String{
    Log.d("cjq", "gettokenstart : ${Thread.currentThread()}")
    delay(300)
    Log.d("cjq", "gettoken : ${Thread.currentThread()}")
    return "sdf"
}
suspend fun getString():String{
    Log.d("cjq", "getStringstart : ${Thread.currentThread()}")
    delay(100)
    Log.d("cjq", "getString : ${Thread.currentThread()}")
    return "sdf"
}
fun getBody():String{
    Log.d("cjq", "getBody : ${Thread.currentThread()}")
    return "body"
}

D/cjq: out : Thread[main,5,main]
D/cjq: launch : Thread[DefaultDispatcher-worker-1,5,main]
D/cjq: gettokenstart : Thread[DefaultDispatcher-worker-3,5,main]
D/cjq: gettoken : Thread[DefaultDispatcher-worker-3,5,main]
D/cjq: token:sdf
D/cjq: getStringstart : Thread[DefaultDispatcher-worker-2,5,main]
D/cjq: getString : Thread[DefaultDispatcher-worker-2,5,main]
D/cjq: getBody : Thread[DefaultDispatcher-worker-1,5,main]
private fun test2() {
    GlobalScope.launch(Dispatchers.IO) {
        Log.d("cjq", "launch : ${Thread.currentThread()}")
        val token = GlobalScope.async {
           return@async getToken()
        }
        Log.d("cjq","token:$token")
        val string = GlobalScope.async {
            return@async getString()
        }
        getBody()

    }
    Log.d("cjq", "out : ${Thread.currentThread()}")
}
suspend fun getToken():String{
    Log.d("cjq", "gettokenstart : ${Thread.currentThread()}")
    delay(300)
    Log.d("cjq", "gettoken : ${Thread.currentThread()}")
    return "sdf"
}
suspend fun getString():String{
    Log.d("cjq", "getStringstart : ${Thread.currentThread()}")
    delay(100)
    Log.d("cjq", "getString : ${Thread.currentThread()}")
    return "sdf"
}
fun getBody():String{
    Log.d("cjq", "getBody : ${Thread.currentThread()}")
    return "body"
}
D/cjq: out : Thread[main,5,main]
D/cjq: launch : Thread[DefaultDispatcher-worker-1,5,main]
D/cjq: token:DeferredCoroutine{Active}@d6f7b86
D/cjq: gettokenstart : Thread[DefaultDispatcher-worker-3,5,main]
D/cjq: getBody : Thread[DefaultDispatcher-worker-1,5,main]
D/cjq: getStringstart : Thread[DefaultDispatcher-worker-2,5,main]
D/cjq: getString : Thread[DefaultDispatcher-worker-3,5,main]
D/cjq: gettoken : Thread[DefaultDispatcher-worker-3,5,main]
private fun test2(){
    runBlocking {
        Log.d("cjq", "run:${Thread.currentThread().name}")
        delay(1000)
        Log.d("cjq","runblocking")
    }
    Log.d("cjq", "test:${Thread.currentThread().name}")
    Thread.sleep(2000)
    Log.d("cjq","sleep")
}
 D/cjq: run:main
 D/cjq: runblocking
 D/cjq: test:main
 D/cjq: sleep
private fun test2() {
    GlobalScope.launch(Dispatchers.Main) {
        Log.d("cjq", "launch : ${Thread.currentThread()}")
        getToken()
        getString()
        getBody()
    }
    Log.d("cjq", "out : ${Thread.currentThread()}")
}
suspend fun getToken():String{
    delay(300)
    Log.d("cjq", "gettoken : ${Thread.currentThread()}")
    return "sdf"
}
suspend fun getString():String{
    delay(100)
    Log.d("cjq", "getString : ${Thread.currentThread()}")
    return "sdf"
}
fun getBody():String{
    Log.d("cjq", "getBody : ${Thread.currentThread()}")
    return "body"
}
 D/cjq: out : Thread[main,5,main]
 D/cjq: launch : Thread[main,5,main]
 D/cjq: gettoken : Thread[main,5,main]
 D/cjq: getString : Thread[main,5,main]
 D/cjq: getBody : Thread[main,5,main]  

多协程多suspend

private fun test2() {
    GlobalScope.launch(Dispatchers.Main) {
        Log.d("cjq", "launch : ${Thread.currentThread()}")
        val token = GlobalScope.launch {
           getToken()
        }
        val string = GlobalScope.launch {
            getString()
        }
        getBody()
    }
    Log.d("cjq", "out : ${Thread.currentThread()}")
}
suspend fun getToken():String{
    delay(300)
    Log.d("cjq", "gettoken : ${Thread.currentThread()}")
    return "sdf"
}
suspend fun getString():String{
    delay(100)
    Log.d("cjq", "getString : ${Thread.currentThread()}")
    return "sdf"
}
fun getBody():String{
    Log.d("cjq", "getBody : ${Thread.currentThread()}")
    return "body"
}
D/cjq: out : Thread[main,5,main]
D/cjq: launch : Thread[main,5,main]
D/cjq: getBody : Thread[main,5,main]
D/cjq: getString : Thread[DefaultDispatcher-worker-2,5,main]
D/cjq: gettoken : Thread[DefaultDispatcher-worker-2,5,main]

多协程多suspend使用async,可以用来控制协程执行顺序

private fun test2() {
    GlobalScope.launch(Dispatchers.Main) {
        Log.d("cjq", "launch : ${Thread.currentThread()}")
        val token = GlobalScope.async {
            return@async getToken()
        }.await()
        val string = GlobalScope.async {
            return@async getString()
        }.await()
        getBody()
    }
    Log.d("cjq", "out : ${Thread.currentThread()}")
}
suspend fun getToken():String{
    delay(300)
    Log.d("cjq", "gettoken : ${Thread.currentThread()}")
    return "sdf"
}
suspend fun getString():String{
    delay(100)
    Log.d("cjq", "getString : ${Thread.currentThread()}")
    return "sdf"
}
fun getBody():String{
    Log.d("cjq", "getBody : ${Thread.currentThread()}")
    return "body"
}
 D/cjq: out : Thread[main,5,main]
 D/cjq: launch : Thread[main,5,main]
 D/cjq: gettoken : Thread[DefaultDispatcher-worker-2,5,main]
 D/cjq: getString : Thread[DefaultDispatcher-worker-2,5,main]
 D/cjq: getBody : Thread[main,5,main]

协程挂起后恢复所处线程:哪个线程恢复的协程,协程运行在哪个线程

private fun test2() {
    GlobalScope.launch(Dispatchers.IO) {
        Log.d("cjq", "launch : ${Thread.currentThread()}")
        val token = GlobalScope.async {
           return@async getToken()
        }.await()
        Log.d("cjq","token:$token")
        val string = GlobalScope.async {
            return@async getString()
        }.await()
        getBody()

    }
    Log.d("cjq", "out : ${Thread.currentThread()}")
}
suspend fun getToken():String{
    Log.d("cjq", "gettokenstart : ${Thread.currentThread()}")
    delay(300)
    Log.d("cjq", "gettoken : ${Thread.currentThread()}")
    return "sdf"
}
suspend fun getString():String{
    Log.d("cjq", "getStringstart : ${Thread.currentThread()}")
    delay(100)
    Log.d("cjq", "getString : ${Thread.currentThread()}")
    return "sdf"
}
fun getBody():String{
    Log.d("cjq", "getBody : ${Thread.currentThread()}")
    return "body"
}

D/cjq: out : Thread[main,5,main]
D/cjq: launch : Thread[DefaultDispatcher-worker-1,5,main]
D/cjq: gettokenstart : Thread[DefaultDispatcher-worker-3,5,main]
D/cjq: gettoken : Thread[DefaultDispatcher-worker-3,5,main]
D/cjq: token:sdf
D/cjq: getStringstart : Thread[DefaultDispatcher-worker-2,5,main]
D/cjq: getString : Thread[DefaultDispatcher-worker-2,5,main]
D/cjq: getBody : Thread[DefaultDispatcher-worker-1,5,main]
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.2.0'//lifecycleScope
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'//viewModelScope
class MainFragment : Fragment(){
    val model:RvViewModel by viewModels()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        lifecycleScope.launch {  }
    }
}
class RvViewModel : ViewModel() {
    fun getData() {
        viewModelScope.launch(Dispatchers.IO) { 
        }
    }
}

1、GlobalScope的生命周期是process级别的,即使activity或fragment销毁,协程仍在执行
2、lifecycleScope的作用域CoroutineScope绑定到lifecycleowner的生命周期,取消此作用域,协程销毁,lifecycleowner生命周期可以绑定到activity中,所以lifecycleScopr间接绑定到Activity和Fragment的生命周期。只能用于activity或fragment
3、viewmodelScope的作用域CoroutineScope的作用域绑定到viewmodel,viewmodel销毁,作用域清除,只能用于viewmodel

    private fun initTest() {
        GlobalScope.launch {
            kotlin.runCatching {
                var j: Int = updateUser()
                Log.d("cjq-1", "$j")
                return@runCatching j
            }.onSuccess {
                Log.d("cjq-2", "$it")
            }.onFailure {
                Log.d("cjq-3", "${it.message}")
            }
        }
    }

    private fun updateUser(): Int {
//        return 2
        throw Exception("sdf")
    }
    D/cjq-3: sdf
    private fun initTest() {
        GlobalScope.launch {
            kotlin.runCatching {
                var j: Int = updateUser()
                Log.d("cjq-1", "$j")
                return@runCatching j
            }.onSuccess {
                Log.d("cjq-2", "$it")
            }.onFailure {
                Log.d("cjq-3", "${it.message}")
            }
        }
    }

    private fun updateUser(): Int {
        return 2
//        throw Exception("sdf")
    }
    D/cjq-1: 2
    D/cjq-2: 2
private val mPending = AtomicBoolean(false)

@MainThread
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
    super.observe(owner) { t ->
        if (mPending.compareAndSet(true, false)) {
            observer.onChanged(t)
        }
    }
}

@MainThread
override fun setValue(t: T?) {
    mPending.set(true)
    super.setValue(t)
}
public final boolean compareAndSet(boolean expect, boolean update) {
    return U.compareAndSwapInt(this, VALUE,
                               (expect ? 1 : 0),
                               (update ? 1 : 0));
}

compareAndSet()方法:
1、比较mPenging值和expect值是否相等,相等则执行方法
2、将mPending赋值为update
以上的方法则为只有在setValue()方法执行后才会执行observer.onChanged(),并执行线程同步操作

上一篇下一篇

猜你喜欢

热点阅读