天天看點

kotlin Coroutine協程什麼是協程?什麼是程序和線程?開始使用

kotlin Coroutine協程

  • 什麼是協程?
    • 官方描述:
    • 協程起源
    • 些語言應用到了協程?
    • 協程優點
      • 舉例說明
        • 異步代碼 & 回調地獄
        • 地獄到天堂(使用協程)
  • 什麼是程序和線程?
    • 程序是什麼呢?
    • 線程又是什麼呢?
      • Java中線程具有五種狀态
      • 線程和協程的關系
  • 開始使用
    • 環境準備
    • 建立協程的幾種方式
      • 使用方式一:launch:Job(最常用,不阻塞)
      • 使用方式二:runBlocking(阻塞)
      • 使用方式三:async/await:Deferred(不阻塞)
      • 協程中的一些關鍵名稱
      • 關系
      • 排程器Dispatchers
      • suspend

什麼是協程?

官方描述:

協程(英文Coroutines)通過将複雜性放入庫來簡化異步程式設計。程式的邏輯可以在協程中順序地表達,而底層庫會為我們解決其異步性。該庫可以将使用者代碼的相關部分包裝為回調、訂閱相關事件、在不同線程(甚至不同機器)上排程執行,而代碼則保持如同順序執行一樣簡單。
說人話: 協程就像非常輕量級的線程,協程依賴于線程,并且内部實作了相關異步操作

協程起源

「協程 Coroutines」源自 Simula 和 Modula-2 語言,這個術語早在 1958 年就被 Melvin Edward

Conway 發明并用于建構彙程式設計式,說明協程是一種程式設計思想,并不局限于特定的語言。

些語言應用到了協程?

  • Lua語言

    Lua從5.0版本開始使用協程,通過擴充庫coroutine來實作。

  • Python語言

    正如剛才所寫的代碼示例,python可以通過 yield/send 的方式實作協程。在python 3.5以後, async/await 成為了更好的替代方案。

  • Go語言

    Go語言對協程的實作非常強大而簡潔,可以輕松建立成百上千個協程并發執行。

  • Java語言

    如上文所說,Java語言并沒有對協程的原生支援,但是某些開源架構模拟出了協程的功能,有興趣的小夥伴可以看一看Kilim架構的源碼:

    https://github.com/kilim/kilim

協程優點

  • 輕量級,占用更少的系統資源;(線程的代碼,占用的記憶體幾乎是使用協程的兩倍)
  • 高效
  • 挂起函數,不會造成線程阻塞
  • 異步邏輯同步化表達

舉例說明

異步代碼 & 回調地獄

比如我們有個需求,發起了一個異步請求,從服務端查詢使用者的資訊,通過 CallBack 傳回 response:

kotlin Coroutine協程什麼是協程?什麼是程式和線程?開始使用

如果現在需求修改了,查詢使用者資訊→查找該使用者的好友清單→查找該好友的動态(代碼看起來非常臃腫)

kotlin Coroutine協程什麼是協程?什麼是程式和線程?開始使用
kotlin Coroutine協程什麼是協程?什麼是程式和線程?開始使用

地獄到天堂(使用協程)

kotlin Coroutine協程什麼是協程?什麼是程式和線程?開始使用
是不是簡潔到了極緻?這就是 Kotlin 協程的魅力:以同步的方式完成異步任務。

為了更好的了解,在使用協程之前,再講解一下線程和程序

什麼是程序和線程?

kotlin Coroutine協程什麼是協程?什麼是程式和線程?開始使用

程序是什麼呢?

直白地講,程序就是應用程式的啟動執行個體。比如我們運作一個遊戲,打開一個軟體,就是開啟了一個程序。

程序擁有代碼和打開的檔案資源、資料資源、獨立的記憶體空間。

線程又是什麼呢?

線程從屬于程序,是程式的實際執行者。一個程序至少包含一個主線程,也可以有更多的子線程。

線程擁有自己的棧空間。

對作業系統來說,線程是最小的執行單元,程序是最小的資源管理單元。

無論程序還是線程,都是由作業系統所管理的。

Java中線程具有五種狀态

kotlin Coroutine協程什麼是協程?什麼是程式和線程?開始使用

線程不同狀态之間的轉化是誰來實作的呢?是JVM嗎?

并不是。JVM需要通過作業系統核心中的TCB(Thread Control Block)子產品來改變線程的狀态,這一過程需要耗費一定的CPU資源。 在 Java 的 API 中,Thread 類是實作線程最基本的類,每建立一個 Thread 對象,就代表着在作業系統核心啟動了一個線程,如果我們閱讀 Thread 類的源碼,可以發現,它的内部實作是大量的 JNI 調用,因為線程的實作必須由作業系統直接提供支援。

線程和協程的關系

kotlin Coroutine協程什麼是協程?什麼是程式和線程?開始使用
  • 輕量級、高效
線程是由系統排程的,線程切換或線程阻塞的開銷都比較大
  • 依賴于線程
不能脫離線程而運作
  • 挂起時不阻塞線程
協程底層庫也是異步處理阻塞任務,但是這些複雜的操作被底層庫封裝起來,協程代碼的程式流是順序的
  • 一個線程可建立任意個協程
  • 不同的線程之間切換
  • 協程可控
協程底層庫也是異步處理阻塞任務,但是這些複雜的操作被底層庫封裝起來,協程代碼的程式流是順序的

開始使用

環境準備

kotlin Coroutine協程什麼是協程?什麼是程式和線程?開始使用

建立協程的幾種方式

kotlin Coroutine協程什麼是協程?什麼是程式和線程?開始使用

使用方式一:launch:Job(最常用,不阻塞)

kotlin Coroutine協程什麼是協程?什麼是程式和線程?開始使用
kotlin Coroutine協程什麼是協程?什麼是程式和線程?開始使用

使用方式二:runBlocking(阻塞)

kotlin Coroutine協程什麼是協程?什麼是程式和線程?開始使用
kotlin Coroutine協程什麼是協程?什麼是程式和線程?開始使用

使用方式三:async/await:Deferred(不阻塞)

kotlin Coroutine協程什麼是協程?什麼是程式和線程?開始使用

協程中的一些關鍵名稱

kotlin Coroutine協程什麼是協程?什麼是程式和線程?開始使用

關系

kotlin Coroutine協程什麼是協程?什麼是程式和線程?開始使用

作用域和上下文的差別

隻在于使用目的的不同——作用域用于管理協程;而上下文隻是一個記錄協程運作環境的集合

排程器Dispatchers

kotlin Coroutine協程什麼是協程?什麼是程式和線程?開始使用

suspend

suspend 修飾的方法會在在編譯期間被編譯器做特殊處理,這種處理被成為CPS(續體轉換風格) 轉化,suspend 方法會被包裹成 Continuation

Kotlin 編譯器将會為每個挂起函數建立一個狀态機,這個狀态機将為我們管理協程的操作!

挂起函數必須在協程或者另一個挂起函數裡被調用。

繼續閱讀