Kotlin协程

创建协程的API:

launch:
//创建协程
GlobalScope.launch()     

//CoroutineScope是协程本身,类比Thread
//实际上launch函数长这样,它是CoroutineScope的方法
public fun CoroutineScope.launch(
	//CoroutineContext是协程上下文,主要包括 Job 和 CoroutineDispatcher 
    context: CoroutineContext = EmptyCoroutineContext,
    //启动模式,包括DEAFAULT,ATOMIC,UNDISPATCHED,LAZY 
    //LAZY模式需要手动调用job.start()才会启动
    start: CoroutineStart = CoroutineStart.DEFAULT,
    //闭包参数,协程实际的执行体就写在里面
    block: suspend CoroutineScope.() -> Unit
): Job		//它返回了一个Job对象

CoroutineDispatcher是协程调度器,决定协程所在的线程或线程池,它有四种模式:

Dispatchers.Default
Dispatchers.IO
Dispatchers.Main 				//主线程
Dispatchers.Unconfined 			//没指定,就是在当前线程

Job: 协程构建函数的返回值,如:

var job:Job = GlobalScope.launch( start = CoroutineStart.LAZY ){
}

job.start()							// 启动协程,除lazy模式,协程都不需要手动启动
job.join() 							// 等待协程执行完毕
job.cancel() 						// 取消一个协程
job.cancelAndJoin()					// 等待协程执行完毕然后再取消
async

async和launch的唯一区别就是,async 返回一个Deferred 对象,Deferred 继承自 Job,只增加了一个await方法,await方法接收的是闭包参数的返回值,例如:

 GlobalScope.launch(Dispatchers.Unconfined) {
        val deferred = GlobalScope.async{
            delay(1000)
            return@async "Deferred Test"
        }
        //deferred.await()是一个suspend方法,必须要写在协程体中
        //这里就可以获取到"Deferred Test"了
        val result = deferred.await()		
}
runBlocking
   fun main(args: Array<String>) {
        runBlocking {
        	//t = 0s
            delay(1000)
            println("1")
        }
        //t = 1s
        Thread.sleep(2000)
        //t = 2s
        println("2")
  }

协程的执行顺序:

1.无挂起函数时按顺序执行

	GlobalScope.launch(Dispatchers.Unconfined) {
          for (i in 1..6) {
               println("协程"+i)
          }
    }
    //执行完协程中的逻辑才会执行以下代码
    for (i in 1..8) {
        println("主线程"+i)
    }

2.单协程中,协程体中的挂起函数按顺序执行

    fun foo() {
        GlobalScope.launch {
        	//t = 0s
            getId()
            //t = 3s
            getToken()
            //t = 6s
            login()

        }
    }

    private suspend fun getToken(): String {
        delay(3000)
        return "Token"
    }

    private suspend fun getId(): String {
        delay(3000)
        return "UserId"
    }

    private fun login(): String {
        return "Login Success"
    }

3.多协程中,协程体中的挂起函数按顺序执行

    GlobalScope.launch(Dispatchers.Unconfined){
        var token = GlobalScope.async(Dispatchers.Unconfined) {
            return@async getId()
       }.await()
       
       var response = GlobalScope.async(Dispatchers.Unconfined) {
            return@async getToken()
       }.await()
       login()
   }

执行发现也是顺序执行的,因为await是个suspend函数,它将最外层协程挂起了,和情况2实际是一样的

挂起函数恢复后运行在哪个线程:

对于Dispatchers.DefaultDispatchers.IODispatchers.Main,由于它们属于Confined dispatcher,所以协程会一直运行在指定的线程上,而对于Dispatchers.Unconfined
例如:

 launch() { 									
        println("${Thread.currentThread().name}")				//Default
        delay(100)
        println("${Thread.currentThread().name}")				//Default
 }

 launch(Dispatchers.Unconfined) {
        println("${Thread.currentThread().name}")				//main
        delay(100)
        println("${Thread.currentThread().name}")				//DefaultExecutor
    }

你可能感兴趣的:(Kotlin协程)