協程入門(一):啓動與掛起

什麼是協程

協程: 是一種更爲靈活高效的"用戶線程",可以選擇異步仍是同步執行,指定運行的線程。編程

異步、同步編程 : 是指的協程可以選擇自身的啓動模式,在當前線程堵塞式運行,仍是在後臺線程異步執行;bash

指定運行線程:可以方便的選擇執行的線程是後臺線程仍是UI主線程;微信

在併發處理上會比使用線程來得更加的高效。併發

進程、線程、協程關係

進程 > 線程 > 協程, 即一個進程能夠包含多個線程,一個線程上面能夠運行多個協程。異步

啓動方式

目前從非協程環境中啓動協程環境主要有三種方式async

啓動方式 說明
runBlocking 建立新的協程,運行在當前線程上,因此會堵塞當前線程,直到協程體結束
GlobalScope.launch 啓動一個新的線程,在新線程上建立運行協程,不堵塞當前線程
GlobalScope.asyn 啓動一個新的線程,在新線程上建立運行協程,而且不堵塞當前線程,支持 經過await獲取返回值

runBlocking

建立新的協程運行在當前線程上,因此會堵塞當前線程,直到協程體結束ui

適用範圍

用於啓動一個協程任務,一般只用於啓動最外層的協程,例如線程環境切換到協程環境spa

示例

/**
     * 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

建立新的協程,默認運行在後臺新的線程中,而且不堵塞當前線程線程

適用範圍

適用範圍: 須要啓動異步線程處理的狀況code

示例
/**
     * 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)
        }
    }
複製代碼

微信公衆號

相關文章
相關標籤/搜索