【碼上開學】到底什麼是「非阻塞式」掛起?協程真的更輕量級嗎?

本期做者:git

視頻:扔物線(朱凱)github

文章:Lewis(姚文欽)編程

你們好,我是扔物線朱凱。今天又是協程,不過今天有一些不同:api

  1. 今天是協程的最後一期(起碼近期內最後一期);
  2. 今天的視頻最後,我 dui 了 Kotlin 官方。好刺激啊。

這期主要是解釋一下掛起的「非阻塞式」是怎麼回事,以及對一些最多見的誤導性言論進行一下平常打臉——固然了目的固然不是打誰的臉,我沒那閒工夫,主要是給你們開個霧。網絡

更多的話就不說了,來看視頻吧:多線程

慣例,我不知道怎麼在掘金髮視頻,因此你們能夠點 這裏 去嗶哩嗶哩,或者點擊 這裏 去 YouTube 看。架構

如下內容來自文章做者 Lewisapp

你們好,協程的素質三連最後一連終於來了,挖坑容易填坑難。框架

這段時間真的太忙了,不過咱們即刻 Android 團隊也對作好「碼上開學」的意義又有了新的認識。編程語言

接觸過大公司的朋友都知道,不少公司會把一些技術的分享列爲公司機密,僅限內部分享,你只有加入了公司以後才能看,而且還不能傳播出來,而這些被列爲機密的東西一般有如下特色:

  • 分享完後鮮有更新,不少知識點已通過時
  • 不涉及具體的業務機密,僅僅是不想讓公司外的人員學到
  • 沒法進行技術交流,也形不成好的技術社區

但願上面說的沒有戳中你所在的公司,這裏沒有任何 diss 的意思,因此咱們要作好「碼上開學」,也但願更多有相同志向的業內同行一塊兒參與進來,經過碼上開學,咱們想表達這樣的技術理念:

  • 文章的價值不是隻有技術深度這一個維度,深刻淺出,找到本質纔是重點
  • 文章不是炫技、引戰的地方,是你們平等交流,互助成長的地方
  • 技術社區和 Android 同樣是生態,須要你們一同維護,而不是各人自掃門前雪,休管他人瓦上霜

在協程系列的前兩篇文章中,咱們介紹了:

  • 協程就是個線程框架
  • 協程的掛起本質就是線程切出去再切回來

由於時間比較久遠了,忘了也很正常,不過今天咱們要說的這個「非阻塞式」的概念,即便你沒有協程的基礎,也能夠看懂。

什麼是「非阻塞式掛起」

非阻塞式是相對阻塞式而言的。

編程語言中的不少概念其實都來源於生活,就像脫口秀的段子同樣。

線程阻塞很好理解,現實中的例子就是交通堵塞,它的核心有 3 點:

  • 前面有障礙物,你過不去(線程卡了)
  • 須要等障礙物清除後才能過去(耗時任務結束)
  • 除非你繞道而行(切到別的線程)

從語義上理解「非阻塞式掛起」,講的是「非阻塞式」這個是掛起的一個特色,也就是說,協程的掛起,就是非阻塞式的,協程是不講「阻塞式的掛起」的概念的。

咱們講「非阻塞式掛起」,其實它有幾個前提:並無限定在一個線程裏說這件事,由於掛起這件事,原本就是涉及到多線程。

就像視頻裏講的,阻塞不阻塞,都是針對單線程講的,一旦切了線程,確定是非阻塞的,你都跑到別的線程了,以前的線程就自由了,能夠繼續作別的事情了。

因此「非阻塞式掛起」,其實就是在講協程在掛起的同時切線程這件事情。

爲何要講非阻塞式掛起

既然第三篇說的「非阻塞式掛起」和第二篇的「掛起要切線程」是同一件事情,那還有講的必要嗎?

是有的。由於它在寫法上和單線程的阻塞式是同樣的。

協程只是在寫法上「看起來阻塞」,實際上是「非阻塞」的,由於在協程裏面它作了不少工做,其中有一個就是幫咱們切線程。

第二篇講掛起,重點是說切線程先切過去,而後再切回來。

第三篇講非阻塞式,重點是說線程雖然會切,但寫法上和普通的單線程差很少。

讓咱們來看看下面的例子:

🏝️
main {
    GlobalScope.launch(Dispatchers.Main) {
        // 👇 耗時操做
        val user = suspendingRequestUser()
        updateView(user)
    }
    
    private suspend fun suspendingRequestUser() : User = withContext(Dispatchers.IO) {
        api.requestUser()
    }
}
複製代碼

從上面的例子能夠看到,耗時操做和更新 UI 的邏輯像寫單線程同樣放在了一塊兒,只是在外面包了一層協程。

而正是這個協程解決了原來咱們單線程寫法會卡線程這件事。

阻塞的本質

首先,全部的代碼本質上都是阻塞式的,而只有比較耗時的代碼纔會致使人類可感知的等待,好比在主線程上作一個耗時 50 ms 的操做會致使界面卡掉幾幀,這種是咱們人眼能觀察出來的,而這就是咱們一般意義所說的「阻塞」。

舉個例子,當你開發的 app 在性能好的手機上很流暢,在性能差的老手機上會卡頓,就是在說同一行代碼執行的時間不同。

視頻中講了一個網絡 IO 的例子,IO 阻塞更可能是反映在「等」這件事情上,它的性能瓶頸是和網絡的數據交換,你切多少個線程都沒用,該花的時間一點都少不了。

而這跟協程半毛錢關係沒有,切線程解決不了的事情,協程也解決不了。

協程與線程

協程咱們講了 3 期,Kotlin 協程和線程是沒法脫離開講的。

別的語言我不說,在 Kotlin 裏,協程就是基於線程來實現的一種更上層的工具 API,相似於 Java 自帶的 Executor 系列 API 或者 Android 的 Handler 系列 API。

只不過呢,協程它不只提供了方便的 API,在設計思想上是一個基於線程的上層框架,你能夠理解爲新造了一些概念用來幫助你更好地使用這些 API,僅此而已。

就像 ReactiveX 同樣,爲了讓你更好地使用各類操做符 API,新造了 Observable 等概念。

說到這裏,Kotlin 協程的三大疑問:協程是什麼、掛起是什麼、掛起的非阻塞式是怎麼回事,就已經所有講完了。很是簡單:

  • 協程就是切線程;
  • 掛起就是能夠自動切回來的切線程;
  • 掛起的非阻塞式指的是它能用看起來阻塞的代碼寫出非阻塞的操做,就這麼簡單。

固然了,這幾句是總結,它們背後的原理你是必定要掌握住的。若是忘了,再去把以前的視頻和文章看一遍就好。

視頻中還糾正了官方文檔裏面的一個錯誤,這裏就再也不重複了,最後想表達一點:

Kotlin 協程並無脫離 Kotlin 或者 JVM 創造新的東西,它只是將多線程的開發變得更簡單了,能夠說是由於 Kotlin 的誕生而順其天然出現的東西,從語法上看它很神奇,但從原理上講,它並非魔術。

但願經過協程系列的講解能幫助讀者上手 Kotlin 協程,再也不以爲懼怕不敢上手,歡迎繼續關注「碼上開學」的後續文章,期待和你共同進步。

練習題

使用協程實現一個網絡請求:

  • 等待時顯示 Loading;
  • 請求成功或者出錯讓 Loading 消失;
  • 請求失敗須要提示用戶請求失敗了;
  • 讓你的協程寫法上看上去像單線程。

做者介紹

視頻做者

扔物線(朱凱)
  • 碼上開學創始人、項目管理人、內容模塊規劃者和視頻內容做者。
  • Android GDE( Google 認證 Android 開發專家),前 Flipboard Android 工程師。
  • GitHub 全球 Java 排名第 92 位,在 GitHub 上有 6.6k followers 和 9.9k stars。
  • 我的的 Android 開源庫 MaterialEditText 被全球多個項目引用,其中包括在全球擁有 5 億用戶的新聞閱讀軟件 Flipboard 。
  • 曾屢次在 Google Developer Group Beijing 線下分享會中擔任 Android 部分的講師。
  • 我的技術文章《給 Android 開發者的 RxJava 詳解》發佈後,在國內多個公司和團隊內部被轉發分享和做爲團隊技術會議的主要資料來源,以及逆向傳播到了美國一些如 Google 、 Uber 等公司的部分華人團隊。
  • 創辦的 Android 高級進階教學網站 HenCoder 在全球華人 Android 開發社區享有至關的影響力。
  • 以後創辦 Android 高級開發教學課程 HenCoder Plus ,學員遍及全球,有來自阿里、頭條、華爲、騰訊等知名一線互聯網公司,也有來自中國臺灣、日本、美國等地區的資深軟件工程師。

文章做者

Lewis(姚文欽)

Lewis(姚文欽),即刻 Android 工程師。2017年加入即刻,參與即刻 4.0 到 6.0 版本的架構設計和與產品迭代。多年 Android 開發經驗,如今負責 Android 端多媒體中臺基礎建設。

相關文章
相關標籤/搜索