Kotlin协程N问(三):runBlocking, launch ,withContext ,async,doAsync

54 阅读1分钟

一个异步编程的框架

1、怎么去用?

GlobalScope.launch和runBlocking,前者不阻塞,后者会阻塞。

//从上面运行结果可以看出,通过CoroutineScope.launch开启一个协程,协程体里的任务时就会先挂起(suspend),
// 让CoroutineScope.launch后面的代码继续执行,直到协程体内的方法执行完成再自动切回来所在的上下文回调结果。
//!!!所以launch是最后执行的

 Log.e(TAG,"2.BtnClick1.... [当前线程为:${Thread.currentThread().name}]")


 CoroutineScope(Dispatchers.Main).launch{
    Log.e(TAG,"1.执行CoroutineScope?????????.... [当前线程为:${Thread.currentThread().name}]")
    delay(2000)
    Log.e(TAG,"1.执行CoroutineScope.... [当前线程为:${Thread.currentThread().name}]")
}
Log.e(TAG,"2.BtnClick1.... [当前线程为:${Thread.currentThread().name}]")

//!!!runBlocking是最后执行的
//runBlocking里的任务如果是非常耗时的操作时,会一直阻塞当前线程,在实际开发中很少会用到runBlocking
runBlocking {
    delay(2000)
    Log.e(TAG,"1.runBlocking.... [当前线程为:${Thread.currentThread().name}]")
}
Log.e(TAG,"2.BtnClick2.... [当前线程为:${Thread.currentThread().name}]")

//withContext 与 async 它们能获得返回值

2、GlobalScope里边跑两个 能得到返回值

2.1withContext 串行执行的


//        串行执行
        GlobalScope.launch {
            val task1 = withContext(Dispatchers.IO){
                delay(1000)
                Log.e(TAG, "go: ", )
            }
            val task2 = withContext(Dispatchers.IO){
                delay(1000)
                Log.e(TAG, "go2: ", )
            }
            Log.e("TAG", "task1 = $task1  , task2 = $task2 ,")
        }

2.2 async是并行执行的,如果要在得到两个async的结果的话 ,可以用await

GlobalScope.launch {

    //并行执行,但是有个await,所以会等到都好了
    val task1 = async(Dispatchers.IO) {
        delay(2000)
        Log.e("TAG", "1.执行task1.... [当前线程为:${Thread.currentThread().name}]")
        "one"  //返回结果赋值给task1
    }

    val task2 = async(Dispatchers.IO) {
        delay(1000)
        Log.e("TAG", "2.执行task2.... [当前线程为:${Thread.currentThread().name}]")
        "two"  //返回结果赋值给task2
    }
    Log.e("TAG", "task1 = ${task1.await()}  , task2 = ${task2.await()} , 耗时   [当前线程为:${Thread.currentThread().name}]")

}

2.3 async(){}.wait()变回串行

 //变回串行
        //await() 只有在 async 未执行完成返回结果时,才会挂起协程。
        // 若 async 已经有结果了,await() 则直接获取其结果并赋值给变量,此时不会挂起协程。

        CoroutineScope(Dispatchers.Main).launch {
            val time1 = System.currentTimeMillis()

            val task1 = async(Dispatchers.IO) {
                delay(2000)
                Log.e("TAG", "1.执行task1.... [当前线程为:${Thread.currentThread().name}]")
                "one"  //返回结果赋值给task1
            }.await()

            val task2 = async(Dispatchers.IO) {
                delay(1000)
                Log.e("TAG", "2.执行task2.... [当前线程为:${Thread.currentThread().name}]")
                "two"  //返回结果赋值给task2
            }.await()

           Log.e("TAG", "task1 = $task1  , task2 = $task2 , 耗时 ${System.currentTimeMillis() - time1} ms  [当前线程为:${Thread.currentThread().name}]")
        }



       

2.4、doAsync

//  还有个Async 整个线程池的 ,直接子线程中操作完再等到ui线程  anko库的
//        doAsync {
//            Log.e("TAG", " doAsync...   [当前线程为:${Thread.currentThread().name}]")
//            uiThread {
//                Log.e("TAG", " uiThread....   [当前线程为:${Thread.currentThread().name}]")
//            }
//        }