最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

kotlin之協程的理解與使用詳解

 更新時間:2021年09月02日 14:18:55   作者:何33512336  
這篇文章主要介紹了kotlin之協程的理解與使用詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下

前言

        為什么在kotlin要使用協程呢,這好比去了重慶不吃火鍋一樣的道理。協程的概念并不陌生,在python也有提及。任何事務的作用大多是對于所依賴的環(huán)境相應而生的,協程對于kotlin這門語言也不例外。協程的優(yōu)點,總的來說有如下幾點:輕量級,占用更少的系統(tǒng)資源; 更高的執(zhí)行效率; 掛起函數較于實現Runnable或Callable接口更加方便可控; kotlin.coroutine 核心庫的支持,讓編寫異步代碼更加簡單。當然在一些不適應它的用法下以上優(yōu)勢也會成為劣勢。

1.協程定義

協程定義:kotlin官方基于JVM的線程實現的一個并發(fā)任務處理框架,封裝的線程api

  1. 使用方便,不使用回調實現線程切換,使用同步方式寫出異步代碼
  2. 所有的耗時任務保證一定放在后臺執(zhí)行掛起
  3. 函數執(zhí)行完畢之后,協程會把它切換到原先的線程的線程。

2.協程的基本用法

常規(guī)函數中一般都有:call and return,協程在此之外添加了suspend和resume.

  1. suspend 用于暫停執(zhí)行的當前協程,并保存所有的局部變量
  2. resume 用于已暫停的協程中暫停出恢復

supend(掛起函數)是什么,有什么意義

suspend,對協程的掛起并沒有實際作用,其實只是一個提醒,函數創(chuàng)建者對函數的調用者的提醒,提醒調用者我是需要耗時操作,需要用掛起的方式,在協程中使用.

  1. 需要注意的是掛起函數只能在掛起函數或者協程作用域中使用,為什么掛起函數需要在協程作用域中使用?因為普通函數沒有suspend和resume這兩個特性,所以必須要在協程的作用中使用。
  2. 意義:
  3. 語法層面:作為一個標記和提醒。通過報錯來提醒調用者和編譯器,這是一個耗時函數,需要放在后臺執(zhí)行。
  4. 編譯器層面:輔助 Kotlin 編譯器來把代碼轉換成 JVM 的字節(jié)碼。
  5. 怎么自定義suspend函數?
  6. 什么時候定義?
  7. 需要耗時操作的時候,需要定義,例如io耗時操作(請求網絡);獲取數據庫數據;一些等待一會需要的操作;列表排除,json解析等;
  8. 怎么寫suspend函數,給函數前加上suspend 關鍵字,把內容用withContext包起來
suspend fun testSuspendfun(){
      withContext(Dispatchers.IO){
 
      }
  }

協程如何確保主線程安全

  1. Dispatchers.Main 調用程序在Android的主線程中
  2. Dispatchers.IO 適合主線程之外的執(zhí)行磁盤或者網絡io操作,例如文件的讀取與寫入,任何的網絡請求
  3. Dispatcher.Default 適合主線程之外的,cpu的操作,例如json數據的解析,以及列表的排序,

協程的掛起本質:本質就是切線程,完成之后只不過可以自動切回來

協程掛起就是切個線程,在掛起函數執(zhí)行完畢之后,協程會自動的重新切回它原先的線程,也就是稍后會被切回來的線程切換。切回來就是resume,恢復功能是協程,所以suspend函數需要在另一個suspend函數或者協程中調用?!阜亲枞綊炱稹棺枞姆绞綄懗隽朔亲枞姆绞?。

3.協程的創(chuàng)建以及取消

//創(chuàng)建一個協程
 
Val scope = CoroutineScope(Dispatchers.Main+Job())
 
通過Job獲取協程的生命周期
 
scope.launch{
}
 
其他耗時請求,例如從數據庫中獲取數據
 
 scope.async {
 }

在KTX庫為某些生命周期提供自己的CoroutineScope,例如ViewModel中viewModelScope,Lifecycle有l(wèi)ifecycleScope

協程的啟動,launch 啟動新協程而不將結果返回給調用方

//創(chuàng)建之后,不管后續(xù)
launch(){
}

async 啟動一個新協程,并通過deferred的await方法暫停函數

//返回deferred 對象
val deferred async{
 
}
deferred.await()

協程的結構化并發(fā),取消協程

協程的結構化并發(fā),可以讓協程非常便于管理。例如在關閉activity中要取消協程。如果是在線程中,取消所有的線程比較復雜。

取消父協程以及父里面的子協程

  val scope = CoroutineScope(Dispatchers.Main+ Job())
        scope.launch {
            val job = launch {
 
               val job1 =  launch {
                   
                }
            }
            job.cancel()
        }
        scope.cancel()

取消子協程某一個,每一個協程都會返回一個job對象,通過調用job的cancle,可以去取消單個的協程的。

val scope = CoroutineScope(Dispatchers.Main+ Job())
        scope.launch {
            val job = launch {
 
               val job1 =  launch {
                   
                }
            }
            job.cancel()
        }
        scope.cancel()

4.協程中異常處理

  在協程內部中捕獲異常

val scope = CoroutineScope(Dispatchers.Main+ Job())
        scope.launch {
            try {
                
            }catch (e:Exception){
            }
        }

5.協程的優(yōu)勢

        在程序運行過程中某些操作(像是:網絡IO、文件IO、CPU或GUP計算密集型工作等等)可能會耗費大量的時間,在單線程的環(huán)境下可能會造成線程的阻塞,在他們完成之前沒辦去做其它事情。使用傳統(tǒng)方法的話,我們可能會選擇使用多線程來解決這個問題,將這些耗時操作放置到新的線程中去執(zhí)行,使主線程能夠正常的運行。那么本文標題所提到的協程是怎么一回事呢?

        協程可以看作是一個輕量級的線程,他不是由操作系統(tǒng)或是虛擬機來實現的,而是通過編譯器。這意味著相對于線程,協程的開銷更小。大家可以從下面的這個例子中感受一下。

        下面是一段Kotlin使用協程的代碼,創(chuàng)建了100萬個協程 (官方的例子是使用的100K,不過運行時間太短,不好截內存的使用情況)。

fun main(args: Array)= runBlocking {    val jobs= List(1_000_000){
        launch(CommonPool){
            delay(10L)
            println(it)
       }
    }
    jobs.forEach { it.join() }
}

內存使用情況

5b9215a000019f8b07280633.jpg

運行耗時:

5b9215a10001b6ae05540284.jpg

然后是使用線程來進行實現的代碼:

fun main(args: Array) {    val threadList=List(1_000_000){
        Thread{
            Thread.sleep(10L)
            println(it)
        }
    }
    threadList.forEach { it.start();it.join() }
}

內存使用情況:

5b9215a10001c83107280633.jpg

運行耗時:10分鐘以上。

        使用線程的代碼,占用的內存幾乎是使用協程的兩倍。而且從運行時間上看使用協程實現的程序話費的時間要遠遠低于線程的實現方式。單從這兩點來看,協程擁有更高的執(zhí)行效率,占用更少的系統(tǒng)資源。那么Kotlin中的協程是通過什么來實現異步操作的呢?它使用的是一種叫做 掛起 的機制。協程的掛起幾乎是沒有損耗的,換種說法,就是不需要選擇額外的上下文或是操作系統(tǒng)調用。 另外一點, 掛起能很大程度上被用戶庫給控制:我們可以決定在掛起狀態(tài)下具體做些什么,并且圍繞著需求進行優(yōu)化/日志/攔截等操作。

        協程不能隨隨便便就被掛起,只能在一個稱為掛起點的地方,在這里會去調用特別標記的函數。這樣的函數被稱作 掛起函數,因為你調用他們會掛起一個協程(如果允許這次調用的話,庫可以直接進行處理而不需要掛起)。 掛起函數的聲明需要添加suspend修飾符。例如:

suspend fun doSomething(foo: Foo): Bar {
...
}

        掛起函數就像平常使用的函數一樣,可以有參數和返回值,但是他們只能被協程或是其它掛起函數調用。事實上,要想啟動一個協程,至少得有一個掛起函數,并且一般是匿名的(也就是一個掛起lambda表達式)。

        線程往往是沒有返回值(實現Runnable接口),盡管可以通過實現Callable接口來獲得帶返回值的線程。但這與協程在語法層面上的支持,在使用的便捷性上還是有不少差距的。

        協程是通過編譯技術實現的 (不需要虛擬機或操作系統(tǒng)的特別支持),這一點在開頭也提到了。掛起操作通過代碼變換實現?;旧?,每一個掛起函數(可能會進行優(yōu)化,但我們在著不想討論這點)都被轉換成一個狀態(tài)機,那些狀態(tài)與掛起調用相對應。在一個掛起準備好之前,下一狀態(tài)與相關局部變量等一起存儲在編譯器生成的類的字段中。在恢復該協程時,恢復局部變量并且狀態(tài)機從剛好掛起之后的狀態(tài)進行。掛起的協程可以作為保持其掛起狀態(tài)與局部變量的對象來存儲和傳遞。

        許多其它語言實現的異步機制也能制作成庫,在Kotlin的協程中使用。包括:C#和ECMAScript寫的 async/await , channels Go語言寫的 select ;C#和Python寫的 generators/yield 。

到此這篇關于kotlin之協程的理解與使用詳解的文章就介紹到這了,更多相關kotlin之協程內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Hibernate三種狀態(tài)和Session常用的方法

    Hibernate三種狀態(tài)和Session常用的方法

    本文主要介紹了Hibernate三種狀態(tài)和Session常用的方法,具有很好的參考價值,下面跟著小編一起來看下吧
    2017-03-03
  • Java實現生成pdf并解決表格分割的問題

    Java實現生成pdf并解決表格分割的問題

    這篇文章主要為大家詳細介紹了如何利用Java實現生成pdf,并解決表格分割的問題,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-11-11
  • springboot整合redis進行數據操作(推薦)

    springboot整合redis進行數據操作(推薦)

    springboot整合redis比較簡單,并且使用redistemplate可以讓我們更加方便的對數據進行操作。下面通過本文給大家分享springboot整合redis進行數據操作的相關知識,感興趣的朋友一起看看吧
    2017-10-10
  • Java性能調優(yōu)及排查方式

    Java性能調優(yōu)及排查方式

    這篇文章主要介紹了Java性能調優(yōu)及排查方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • java中最大的整數用法分析

    java中最大的整數用法分析

    這篇文章主要介紹了java中最大的整數用法,結合具體實例形式分析了java計算類java.math.BigInteger具體使用技巧,需要的朋友可以參考下
    2017-06-06
  • Java?中很好用的數據結構EnumSet

    Java?中很好用的數據結構EnumSet

    這篇文章主要介紹了Java?中很好用的數據結構EnumSet,EnumMap即屬于一個Map,下文圍繞主題展開詳細內容,需要的小伙伴可以參考參考一下
    2022-05-05
  • SpringBoot修改子模塊Module的jdk版本的方法 附修改原因

    SpringBoot修改子模塊Module的jdk版本的方法 附修改原因

    這篇文章主要介紹了SpringBoot修改子模塊Module的jdk版本的方法 附修改原因,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • java 線程方法join簡單用法實例總結

    java 線程方法join簡單用法實例總結

    這篇文章主要介紹了java 線程方法join簡單用法,結合實例形式總結分析了Java線程join方法的功能、原理及使用技巧,需要的朋友可以參考下
    2019-11-11
  • IDEA 自定義方法注解模板的實現方法

    IDEA 自定義方法注解模板的實現方法

    這篇文章主要介紹了IDEA 自定義方法注解模板的實現方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-09-09
  • springboot如何獲取application.yml里值的方法

    springboot如何獲取application.yml里值的方法

    這篇文章主要介紹了springboot如何獲取application.yml里的值,文章圍繞主題相關自資料展開詳細的內容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-04-04

最新評論

措勤县| 桐庐县| 师宗县| 柳州市| 云南省| 兴和县| 康平县| 康保县| 木里| 昌图县| 双城市| 南汇区| 长春市| 博客| 沙雅县| 洪雅县| 延津县| 松原市| 达尔| 武宣县| 绥化市| 绥德县| 武宁县| 福鼎市| 泊头市| 岳阳市| 阿拉善盟| 宜兰县| 延安市| 武宁县| 璧山县| 多伦县| 临沭县| 伊金霍洛旗| 连云港市| 曲靖市| 阜平县| 进贤县| 利川市| 奈曼旗| 邳州市|