Android-kotlin-coroutine協程的概念

一. 進程,線程,協程 概念

進程與線程
  • 進程是資源分配的最小單位,線程是程序執行的最小單位。html

  • 進程有本身的獨立地址空間,每啓動一個進程,系統就會爲它分配地址空間,創建數據表來維護代碼段、堆棧段和數據段,這種操做很是昂貴。而線程是共享進程中的數據的,使用相同的地址空間,所以CPU切換一個線程的花費遠比進程要小不少,同時建立一個線程的開銷也比進程要小不少。android

爲了加大一個應用可以使用的內存經過多進程來獲取多分內存空間 經過給四大組件指定android:process屬性能夠輕易開啓多進程程序員

  • 線程之間的通訊更方便,同一進程下的線程共享全局變量、靜態變量等數據,而進程之間的通訊須要以通訊的方式(IPC-跨進程通訊)進行。不過如何處理好同步與互斥是編寫多線程程序的難點。

跨進程通訊方式有:數據庫

1. 經過Intent(Bundle)附加extras來傳遞信息bash

2. 經過共享文件來共享數據多線程

3. 採用Binder方式來是想跨進程通訊app

4. 採用ContentProvider異步

5. 採用socketsocket

  • 可是多進程程序更健壯,多線程程序只要有一個線程死掉,整個進程也死掉了,而一個進程死掉並不會對另一個進程形成影響,由於進程有本身獨立的地址空間。

延申到android崩潰一樣道理。async

app中大量Web頁面的使用容易致使App內存佔用巨大,存在內存泄露,崩潰率高等問題,WebView獨立進程的使用是解決Android WebView相關問題的一個合理的方案。

進程與線程

線程與協程

kotlin協程是一種用戶態的輕量級線程。一個進程能夠擁有多個線程同樣,一個線程也能夠擁有多個協程。

協程不是被操做系統內核所管理,而徹底是由程序所控制(也就是在用戶態執行)。

協程的開銷遠遠小於線程的開銷。

協程的特色在因而單線程執行,那和多線程比,協程有何優點?換句話說,協程的出現解決了線程的那些痛點。

  • 極高的執行效率:由於子程序切換不是線程切換,而是由程序自身控制,所以,沒有線程切換的開銷,和多線程比,線程數量越多,協程的性能優點就越明顯;
  • 不須要多線程的鎖機制:由於只有一個線程,也不存在同時寫變量衝突,在協程中控制共享資源不加鎖,只須要判斷狀態就行了,因此執行效率比多線程高不少。

線程與協程

小結:

進程:擁有本身獨立的堆和棧,既不共享堆,也不共享棧,進程由操做系統調度; 線程:擁有本身獨立的棧和共享的堆,共享堆,不共享棧,標準線程由操做系統調度; 協程:擁有本身獨立的棧和共享的堆,共享堆,不共享棧,協程由程序員在協程的代碼裏顯示調度。


二. Kotlin協程基本使用

協程主要是讓原來要使用"異步+回調方式"寫出來複雜代碼,簡化成能夠用看似同步的方式,這樣咱們就能夠按串行的思惟模式去組織本來分散在不一樣上下文的代碼邏輯。也加強了程序的可讀性。

//----例如:僞代碼----
launch(Background) {
  //執行耗時操做
  val bitmap = MediaStore.getBitmap(uri) 
  launch(UI) {
    //更新UI
    imageView.setImageBitmap(bitmap)
  }
}
複製代碼
集成環境
  • 集成kotlin插件
ext.kotlin_version = '1.3.11'
dependencies {
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
複製代碼
  • 引入協程核心庫
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.0"
//或使用android
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.0"
複製代碼
  • experimental啓用聲明
//在module的build.gradle中聲明
kotlin {
    experimental {
        coroutines 'enable'
    }
}
複製代碼
建立
  • launch 建立協程
  • async 建立帶返回值的協程,返回的是 Deferred 類
  • withContext 不建立新的協程,在指定協程上運行代碼塊
  • runBlocking 不是 GlobalScope 的 API,能夠獨立使用,區別是 runBlocking 裏面的 delay 會阻塞線程,而 launch 建立的不會。
//launch
    launch{
          delay(1000)
          println("launch")
     }

    //async 有返回值
    async {
        delay(1000)
        println("async")
        //async 纔能有return
        return@async ""
    }
複製代碼
協程上下文-CoroutineContext
  • Dispatchers.Default 共享後臺線程池裏的線程

  • Dispatchers.Main Android主線程

  • Dispatchers.IO 共享後臺線程池裏的線程

  • Dispatchers.Unconfined 不限制,使用父Coroutine的現場

  • newSingleThreadContext 使用新的線程

/**
  * 上下文
  */
 launch { // 運行在父協程的上下文中,即 runBlocking 主協程
     println("main runBlocking : I'm working in thread ${Thread.currentThread().name}")
 }
 launch(Dispatchers.Default) { // 將會獲取默認調度器
     println("Default : I'm working in thread ${Thread.currentThread().name}")
 }
 launch(Dispatchers.Main) { // Android主線程
     println("Main : I'm working in thread ${Thread.currentThread().name}")
 }
 launch(Dispatchers.IO) { // 共享後臺線程池裏的線程
     println("IO : I'm working in thread ${Thread.currentThread().name}")
 }
 launch(Dispatchers.Unconfined) { // 不受限的——將工做在主線程中
     println("Unconfined : I'm working in thread ${Thread.currentThread().name}")
 }
 launch(newSingleThreadContext("MyOwnThread")) { // 將使它得到一個新的線程
     println("newSingleThreadContext: I'm working in thread ${Thread.currentThread().name}")
 }

複製代碼
協程的掛起和恢復

thread 線程之間採起的是競爭 cpu 時間段的方法,誰搶到誰運行,由系統內核控制,對咱們來講是不可見不可控的。協程不一樣,協程之間不用競爭、誰運行、誰掛起、何時恢復都是由咱們本身控制的。

  • 協程執行時, 協程和協程,協程和線程內代碼是順序運行的。
  • 協程掛起時,就不會執行了,而是等待掛起完成且線程空閒時才能繼續執行。
  • suspend 修飾的方法掛起的是協程自己。
  • await,會阻塞外部協程。適用於多個同級 IO 操做的狀況。await()能夠返回當前協程的執行結果。
runBlocking {
       val deferred1 = async(Dispatchers.Default) {
           println(Thread.currentThread())
           "hello1"
       }

       async(Dispatchers.Default){
           println(Thread.currentThread())
           println("hello2")
           //await()能夠返回當前協程的執行結果: hello1
           println(deferred1.await())
       }

   }
複製代碼

kotlin彙總介紹: kotlin協程指南


工做須要,目前正在寫一個kotlin社交項目。項目中用到room存儲數據,在線程裏經過Dao操做本地數據庫,根據Dao數據返回到主線程更新UI。這個線程切換,使用協程來操做,代碼簡潔易讀。因此花點時間瞭解下!

Kotlin中的協程也是經過線程池來實現的。而在Kotlin中,在線程之上也創建了在線程中相似於Looper+Handler的機制,讓協程能夠在多個線程中切換,以及進行數據的傳遞。

Android子線程切換到UI線程方法總結

相關文章
相關標籤/搜索