欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

Kotlin的協(xié)程和java線程性能的對(duì)比

Kotlin的協(xié)程比java線程性能更好更高效?針對(duì)這個(gè)問題,今天小編總結(jié)這篇有關(guān)Kotlin的協(xié)程和java線程的文章,希望能幫助更多想解決這個(gè)問題的朋友找到更加簡(jiǎn)單易行的辦法。

我們提供的服務(wù)有:成都網(wǎng)站建設(shè)、網(wǎng)站制作、微信公眾號(hào)開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、秦皇島ssl等。為千余家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的秦皇島網(wǎng)站制作公司

一、Kotlin協(xié)程在互聯(lián)網(wǎng)上的主流定義

問題的討論起源于文章《Go語言出現(xiàn)后,Java還是最佳選擇嗎?》,由于之前寫過一段時(shí)間Go語言,對(duì)Go語言有一定的理解,所以當(dāng)時(shí)我看完這篇文章的時(shí)候感到疑惑的是Kotlin到底有沒有完整的實(shí)現(xiàn)類似于Go語言中的協(xié)程機(jī)制?如果有,那么顯然沒有必要費(fèi)這么一大段功夫來魔改JVM的實(shí)現(xiàn)。如果沒有,那么網(wǎng)上那一堆堆的博客難道說的都是錯(cuò)誤的嗎?例如下面百度搜索的結(jié)果:

Kotlin的協(xié)程和java線程性能的對(duì)比

再比如某個(gè)Kotlin的視頻教程(我仔細(xì)觀看了其中關(guān)于協(xié)程部分的講解,與網(wǎng)絡(luò)上流傳的諸如協(xié)程比線程高效是基本一致的)

Kotlin的協(xié)程和java線程性能的對(duì)比

 Kotlin官方網(wǎng)站中的例子:

Kotlin的協(xié)程和java線程性能的對(duì)比

這個(gè)例子說明用Java開10w個(gè)線程很大概率就會(huì)OOM了,但是Kotlin開10w個(gè)協(xié)程就不會(huì)OOM,給人一種Go語言中協(xié)程的感覺。但是真的是這樣么?帶著這個(gè)問題,我們進(jìn)行了一番探索,希望下面的內(nèi)容能幫你解開疑惑。

二、JVM中的Thread和OS的Thread的對(duì)應(yīng)關(guān)系

要搞清楚協(xié)程,首先要搞清楚線程。我們都知道CPU的每個(gè)核心同一時(shí)刻只能執(zhí)行一個(gè)線程。

因此會(huì)帶來一個(gè)問題,當(dāng)線程數(shù)量超過CPU的核心數(shù)量的時(shí)候怎么辦?當(dāng)然是有的線程先暫停一下,然后讓其他的線程走走,每個(gè)線程都有機(jī)會(huì)走一下,最終的目標(biāo)就是讓每個(gè)線程都執(zhí)行完畢。

對(duì)于大部分Java的開發(fā)者來說,JVM都是Oracle提供的,而Android開發(fā)者面對(duì)的就是Art了。但是不管是Oracle的JVM還是谷歌Android的Art,對(duì)于這種主流的JVM實(shí)現(xiàn),他們的線程數(shù)量和操作系統(tǒng)中線程的數(shù)量基本都是保持在1:1的。

也就是說只要在Java語言里面每start Thread 一次,JVM中就會(huì)多一個(gè)Thread,最終就會(huì)多一個(gè)os級(jí)別的線程,在不考慮調(diào)整JVM參數(shù)的情況下,一個(gè)Thread所占用的內(nèi)存大小是1mb。最終的JVM的Thread的調(diào)度還是依賴底層的操作系統(tǒng)級(jí)別的Thread調(diào)度。只要是依賴了操作系統(tǒng)級(jí)別的Thread調(diào)度,那么就不可避免的存在Thread切換帶來的開銷。

每一次Thread的 上下文切換都會(huì)帶來開銷,最終結(jié)果就是如果線程過多,那么最終線程執(zhí)行代碼的時(shí)間就變少,因?yàn)榇蟛糠值腃PU的時(shí)間都消耗在了切換線程上下文上。

這里簡(jiǎn)單證明一下,在Java中Thread和OS的Thread 是1:1的關(guān)系:

Start一個(gè)線程以后,這里最終是要調(diào)用一個(gè)jni方法

Kotlin的協(xié)程和java線程性能的對(duì)比

jdk 目錄下 /src/share/native/java/lang/ 目錄下查詢Thread.c 文件

Kotlin的協(xié)程和java線程性能的對(duì)比

start0 方法最終調(diào)用的JVM_StartThread方法. 再看看這個(gè)方法。

在hotspot 實(shí)現(xiàn)下(注意不是jdk目錄了):

/src/share/vm/prims/   下面的 jvm.cpp 文件

找到這個(gè)方法:

Kotlin的協(xié)程和java線程性能的對(duì)比

最終:

Kotlin的協(xié)程和java線程性能的對(duì)比

繼續(xù)下去就跟平臺(tái)有關(guān)了,考慮到Android底層就是Linux,且現(xiàn)在基本服務(wù)器都是部署在Linux環(huán)境下,可以直接在Linux目錄下找對(duì)應(yīng)的實(shí)現(xiàn):也即是在hotspot 下 src/os/linux/vm/os_linux.cpp 中找到該入口。

Kotlin的協(xié)程和java線程性能的對(duì)比

Kotlin的協(xié)程和java線程性能的對(duì)比

熟悉Linux的人應(yīng)該知道,pthread_create 函數(shù)就是Linux下創(chuàng)建線程的系統(tǒng)函數(shù)了。這就完整的證明了主流JVM中 Java代碼里Thread和最終對(duì)應(yīng)os中的Thread是1:1的關(guān)系。

三、Go語言中的協(xié)程做了什么

再回到協(xié)程,尤其是在Go語言出現(xiàn)以后,協(xié)程在很大程度上可以避免因?yàn)閯?chuàng)建線程過多,最終導(dǎo)致CPU時(shí)間片都來做切線程的操作,從而留給線程自己的CPU時(shí)間過少的問題。

原因就在于Go語言中提供的協(xié)程在完成我們開發(fā)者需要的并發(fā)任務(wù)的時(shí)候, 它的并發(fā)之間的調(diào)度是由Go語言本身完成的,并沒有交給操作系統(tǒng)級(jí)別的Thread切換來完成。也就說協(xié)程本質(zhì)上不過是一個(gè)個(gè)并發(fā)的任務(wù)而已。

在Go語言中,這些并發(fā)的任務(wù)之間相互的調(diào)度都是由Go語言完成,由極少數(shù)的線程來完成n個(gè)協(xié)程的并發(fā)任務(wù),這其中的調(diào)度器并沒有交給操作系統(tǒng)而是交給了自己。

同時(shí)在Go中創(chuàng)建一個(gè)協(xié)程,也僅僅需要4kb的內(nèi)存而已,這跟OS中創(chuàng)建一個(gè)線程所需要的1mb相差甚遠(yuǎn)。

四、Go和Java在實(shí)現(xiàn)并發(fā)任務(wù)上的不同

我們需要注意的是:對(duì)于開發(fā)者而言,并不關(guān)心實(shí)現(xiàn)并發(fā)任務(wù)的到底是線程還是進(jìn)程還是協(xié)程或者是什么其他。我們只關(guān)心提交的并發(fā)任務(wù)是否可以完成。

來看一下這段極簡(jiǎn)的Java代碼。

package com.wuyue;

public class JavaCode {
    public static void main(String[] args) {

        new Thread() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("iqoo" + "  " + Thread.currentThread().getName());
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
        new Thread() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("x27" + "  " + Thread.currentThread().getName());
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();

    }
}

Kotlin的協(xié)程和java線程性能的對(duì)比

這個(gè)執(zhí)行結(jié)果真的很簡(jiǎn)單, 交錯(cuò)打印的IQOO和x27 分別對(duì)應(yīng)著2個(gè)獨(dú)立的線程。所以Java 對(duì)外提供的并發(fā)能力就是依靠不同的Thread來完成。

簡(jiǎn)單來說有多少個(gè)并發(fā)任務(wù),最終反應(yīng)到JVM和OS中就是有多少個(gè)Thread來運(yùn)行。然后我們來看看Go語言中協(xié)程是如何完成類似的事情的。

package main

import (
    "fmt"
    "runtime"
    "strconv"
    "time"

    "golang.org/x/sys/windows"
)

func name(s string) {
    for {
        //為了演示起來方便 我們每個(gè)協(xié)程都是相隔一秒才打印,否則命令行中刷起來太快,不好看執(zhí)行過程
        time.Sleep(time.Second)
        str := fmt.Sprint(windows.GetCurrentThreadId())
        var s = "iqoo" + s + " belong thread " + str
        fmt.Println(s)

    }
}

func main() {
    //邏輯cpu數(shù)量為4,代表我這個(gè)go程序 有4個(gè)p可以使用。每個(gè)p都會(huì)被分配一個(gè)系統(tǒng)線程。
    //這里因?yàn)槲译娔X的cpu是i5 4核心的,所以這里返回的是4. 如果你的機(jī)器是i7 四核心的,那這里返回值就是8了
    //因?yàn)閕ntel的i7 cpu 有超線程技術(shù),簡(jiǎn)單來說就是一個(gè)cpu核心 可以同時(shí)運(yùn)行2個(gè)線程。
    fmt.Println("邏輯cpu數(shù)量:" + strconv.Itoa(runtime.NumCPU()))
    str := fmt.Sprint(windows.GetCurrentThreadId())
    fmt.Println("主協(xié)程所屬線程id =" + str)
    //既然在我機(jī)器上golang默認(rèn)是4個(gè)邏輯線程,那我就將同步任務(wù)擴(kuò)大到10個(gè),看看執(zhí)行結(jié)果
    for i := 1; i <= 10; i++ {
        go name(strconv.Itoa(i))
    }
    // 避免程序過快直接結(jié)束
    time.Sleep(100 * time.Second)

}

可以從下圖中看出來,這種交錯(cuò)的并發(fā)任務(wù)在Go中是可以在一個(gè)線程中完成的,也就驗(yàn)證了協(xié)程的并發(fā)能力并不是線程給的,而是交給Go語言本身自己來完成的。

Kotlin的協(xié)程和java線程性能的對(duì)比

這里要額外注意的是,Go中 有時(shí)候會(huì)出現(xiàn)協(xié)程遷移的情況(即某個(gè)協(xié)程可能一開始在線程id為5的線程跑,過一會(huì)又會(huì)去線程id為10的線程跑),這與Go的調(diào)度器機(jī)制有關(guān),此處就不展開Go調(diào)度器這個(gè)話題。

只要知道 Go中的多個(gè)協(xié)程可以在同一個(gè)線程上執(zhí)行并發(fā)任務(wù)即可??梢岳斫鉃镚o的并發(fā)模型是M(協(xié)程數(shù)):N(線程數(shù))。其中M遠(yuǎn)遠(yuǎn)大于N(指數(shù)級(jí)的差距). 這個(gè)是所有實(shí)現(xiàn)協(xié)程機(jī)制的語言中共有的特性。

五、Kotlin有類似Go中的協(xié)程能力嗎?

那同樣的需求,用Kotlin-JVM可以來完成嗎?答案是不可以。簡(jiǎn)單來說,如果Kotlin-JVM 能提供Go類似的協(xié)程能力,那應(yīng)該能完成如下的需求(但實(shí)際上使用Kotlin語言是無法完成下面的需求的):

  1. N個(gè)并發(fā)任務(wù)分別打印不同的字符串。就跟上述Go和Java的例子一樣。

  2. 在打印的時(shí)候需要打印出所屬的線程id或者線程name,且這id和name要保證一樣。因?yàn)橹挥幸粯?nbsp;才可以證明是在一個(gè)線程上完成了并發(fā)任務(wù),而不是靠JVM的Thread來完成并發(fā)任務(wù)。

六、Kotlin語言中有“鎖”嗎?

我們都知道任何一門現(xiàn)代語言都對(duì)外提供了一定的并發(fā)能力,且一般都在語言層面提供了“鎖”的實(shí)現(xiàn)。比如開啟10個(gè)線程 對(duì)一個(gè)int變量 進(jìn)行++操作,要保證打印出來的順序一定得是1,2,3,4...10. 這樣的Java代碼很好寫,一個(gè)synchronized關(guān)鍵字就可以,我們看看Go中的協(xié)程是否有類似的能力?

package main

import (
    "fmt"
    "strconv"
    "sync"
    "time"

    "golang.org/x/sys/windows"
)

var Mutex sync.Mutex

var i = 0

func name(s string) {
    Mutex.Lock()
    str := fmt.Sprint(windows.GetCurrentThreadId())
    fmt.Println("i==" + strconv.Itoa(i) + "  belong thread id " + str)
    i++
    defer Mutex.Unlock()

}

func main() {
    for i := 1; i <= 10; i++ {
        go name(strconv.Itoa(i))
    }
    // 避免程序過快直接結(jié)束
    time.Sleep(100 * time.Second)

}

Kotlin的協(xié)程和java線程性能的對(duì)比

執(zhí)行結(jié)果很清楚的可以看到,Go中的協(xié)程也是有完整的鎖實(shí)現(xiàn)的。那么Kotlin-JVM的協(xié)程有沒有類似的鎖的實(shí)現(xiàn)呢?經(jīng)過一番搜索,我們首先看看這個(gè)Kotlin官方論壇中的討論https://discuss.kotlinlang.org/t/concurrency-in-kotlin/858

Kotlin的協(xié)程和java線程性能的對(duì)比

這里要提一下的是,很多人都以為Kotlin是谷歌出的,是谷歌的親兒子,實(shí)際上這是一種錯(cuò)誤的想法。Kotlin是JB Team的產(chǎn)物,并不是谷歌親自操刀開發(fā)的,最多算是個(gè)谷歌的干兒子。這個(gè)JB Team 很多人應(yīng)該知道,是IDEA的開發(fā)團(tuán)隊(duì)Android Studio也是脫胎自 IDEA。  

關(guān)于這個(gè)討論,JB Team的意思是說 Kotlin 在自己的語言級(jí)別并沒有實(shí)現(xiàn)一種同步機(jī)制,還是依靠的 Kotlin-JVM中的 Java關(guān)鍵字。尤其是synchronized。既然并發(fā)的機(jī)制都是依靠的JVM中的sync或者是lock來保證,為何稱之為自己是協(xié)程的?

我們知道在主流JVM的實(shí)現(xiàn)中,是沒有協(xié)程的,實(shí)際上JVM也不知道上層的JVM語言到底是啥,反正JVM只認(rèn)class文件,至于這個(gè)class文件是Java編譯出來的,還是Kotlin編譯出來的,或是如groovy等其他語言,那都不重要,JVM不需要知道。

基于這個(gè)討論 我們可以確定的是,Kotlin語言沒有提供鎖的關(guān)鍵字,所有的鎖實(shí)現(xiàn)都交給了JVM自己處理。其實(shí)就是交給線程來處理了。也就是說,雖然 Kotlin-JVM 聲稱自己是協(xié)程,但實(shí)際上干活的還是JVM中Thread那一套東西。

寫一個(gè)簡(jiǎn)單的代碼驗(yàn)證一下,簡(jiǎn)單寫一個(gè)Kotlin的類,因?yàn)镵otlin本身沒有提供同步的關(guān)鍵字,所以這里就用Kotlin官方提供的sync注解。

class PrintTest {
    @Synchronized fun print(){
        println("hello world")
    }

    @Synchronized fun print2(){
        println("hello world")
    }
}

然后我們反編譯看看這個(gè)東西到底是啥。

Kotlin的協(xié)程和java線程性能的對(duì)比

七、Kotlin未來會(huì)支持真協(xié)程嗎?

到了這里,是否說Kotlin 完全是不支持協(xié)程的呢?我認(rèn)為這種說法也是不準(zhǔn)確的,只能說Kotlin-JVM 這個(gè)組合是不支持協(xié)程的。例如我們?cè)贗DEA中新建Kotlin工程的時(shí)候。

Kotlin的協(xié)程和java線程性能的對(duì)比

可以看出來,這里是有選項(xiàng)的,上述的驗(yàn)證,我們只驗(yàn)證了 Kotlin-JVM 是不支持協(xié)程的。那么有沒有一種Kotlin-x 的東西是支持協(xié)程的呢?答案是還真可能有。具體參見官方文檔中Kotlin-Native 平臺(tái)對(duì) 并發(fā)能力的描述:

https://kotlinlang.org/docs/reference/native/concurrency.html(Kotlin-native平臺(tái)就是直接將Kotlin-native編譯成對(duì)應(yīng)平臺(tái)的可執(zhí)行文件也就是機(jī)器碼,并不需要類似于JVM這樣的虛擬機(jī)了)。

我大概翻譯一下其中的幾個(gè)要點(diǎn):Kotlin-Native的并發(fā)能力不鼓勵(lì)使用帶有互斥代碼塊和條件變量的經(jīng)典的面向線程的并發(fā)模型,因?yàn)樵撃P腿菀壮鲥e(cuò)且不可靠。開篇的這句話直接diss的就是JVM的并發(fā)模型。然后繼續(xù)往下看還有驚喜:

Kotlin的協(xié)程和java線程性能的對(duì)比

注意看第一句話,意思就是Kotlin-native提供了一種worker的機(jī)制 來替代線程。目前來看能替代線程的東西也就只有協(xié)程了。也就是說起碼在Kotlin-native這個(gè)平臺(tái)上,Kotlin是真的想提供協(xié)程能力的。目前Kotlin-Native并沒有正式發(fā)布,我們?cè)趇dea上新建Kotlin工程的時(shí)候并沒有看到有Kotlin-Native這個(gè)選項(xiàng)。且Kotlin-Native目前僅支持linux和mac平臺(tái),不支持windows。有興趣且有條件的同學(xué)可以自行搜索Kotlin-Native的編譯方法。

八、主流JVM有計(jì)劃支持協(xié)程嗎?

經(jīng)過前文的分析,我們知道至少目前來看主流的JVM實(shí)現(xiàn)中是沒有協(xié)程的實(shí)現(xiàn)的。但是已經(jīng)有不少團(tuán)隊(duì)在朝著這方面努力,比如說 quasar這個(gè)庫(kù),利用字節(jié)碼注入的方法可以實(shí)現(xiàn)協(xié)程的效果。

在這個(gè)作者加入Oracle之前,OPENJDK也一直在往協(xié)程上努力,項(xiàng)目名loom,這個(gè)應(yīng)該是開源社區(qū)中一直在做的標(biāo)準(zhǔn)協(xié)程實(shí)現(xiàn)了。此外在生產(chǎn)環(huán)境中已經(jīng)協(xié)程上線的效果可以看文章《重塑云上的 Java 語言》。

九、Kotlin中的協(xié)程到底是啥?

那么既然證明了,Kotlin-JVM中的協(xié)程并不是真協(xié)程,那么這個(gè)東西到底是什么,應(yīng)該怎么用?

個(gè)人理解Kotlin-JVM的線程應(yīng)該就僅僅是針對(duì)Java中的Thread做了一次更友好的封裝。讓我們更方便的使用Java中的線程才是Kotlin-JVM中的協(xié)程的真正目的。

本質(zhì)上和Handler,AsyncTask,RxJava 基本是一致的。只不過Kotlin中的協(xié)程比他們更方便一些。這其中最核心的是suspend這個(gè)Kotlin協(xié)程中的關(guān)鍵字。

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        GlobalScope.launch(Dispatchers.Main) {
            getInfo()
            getInfoNoContext()
            Log.v("wuyue", "我又切回來了 in thread " + Thread.currentThread().name)
        }
    }

    /**
     * 掛起就是切換線程 沒其他作用,最多就是切到其他線程以后還可以自動(dòng)切回來,避免過多的callback
     * 所有被suspend標(biāo)記的函數(shù) 要么在協(xié)程里被調(diào)用,要么在其他掛起函數(shù)里被調(diào)用,否則就無法實(shí)現(xiàn)
     * 切走以后又可以切回來的效果
     */
    suspend fun getInfo() {
        /**
         * withContext掛起函數(shù) 內(nèi)部實(shí)現(xiàn)了掛起的流程,suspend其實(shí)并沒有這個(gè)功能
         * kotlin中有很多掛起函數(shù),withContext 應(yīng)該是最常用的
         */
        withContext(Dispatchers.IO) {
            Log.v("wuyue", "getInfo in thread " + Thread.currentThread().name)
        }
    }

    /**
     * 這個(gè)函數(shù) 雖然用suspend標(biāo)記 但是并沒有 用withContext 指定掛起,
     * 所以是沒辦法實(shí)現(xiàn)切線程的作用的,自然而然也就無法實(shí)現(xiàn) 所謂的掛起了
     * 個(gè)人理解這個(gè)suspend關(guān)鍵字的作用就是提醒 調(diào)用者注意 你如果調(diào)用的是一個(gè)被suspend標(biāo)記的函數(shù)
     * 那么一定要注意 這個(gè)函數(shù)可能是一個(gè)后臺(tái)任務(wù),是一個(gè)耗時(shí)的操作,你需要在一個(gè)協(xié)程里使用他。
     * 如果不在協(xié)程里使用,那么kotlin的編譯 就會(huì)直接報(bào)錯(cuò)了。
     *
     *
     * 這點(diǎn)其實(shí)對(duì)于android來講還是很有用的,你所有認(rèn)為耗時(shí)的操作都可以用suspend來標(biāo)記,然后在內(nèi)部指定
     * 這個(gè)協(xié)程的thread 為 io thread, 如果調(diào)用者沒有用launch來 call 這個(gè)方法,那么編譯就報(bào)錯(cuò)。
     * 自然而然就避免了很多 主線程操作io的問題
     *
     */
    suspend fun getInfoNoContext() {
        Log.v("wuyue", "getInfoNoContext in thread " + Thread.currentThread().name)
    }

}

Kotlin的協(xié)程和java線程性能的對(duì)比

這段代碼很簡(jiǎn)單,可以多看一下注釋。很多人都會(huì)被所謂Kotlin協(xié)程的非阻塞式嚇到,其實(shí)你就理解成Kotlin中所宣傳的非阻塞式,無非是用阻塞的寫法來完成非阻塞的任務(wù)而已。

試想一下,我們上述Kotlin中的代碼 如果用Thread來寫,就會(huì)比較麻煩了,甚至還需要用到回調(diào)(如果你不用handler的話)。這一點(diǎn)上Kotlin 協(xié)程的作用和RxJava其實(shí)是一致的,只不過Kotlin做的更徹底,比RxJava更優(yōu)雅更方便更簡(jiǎn)潔。

考慮一種稍微復(fù)雜的場(chǎng)景,某個(gè)頁面需要2個(gè)接口都返回以后才能刷新展示,此種需求,如果用原生的Java concurrent并發(fā)包是可以做的,但是比較麻煩,要考慮各種異常帶來的問題。

比較好的實(shí)現(xiàn)方式是用RxJava的zip操作符來做,在有了Kotlin以后,如果利用Kotlin,這段代碼甚至?xí)葄ip操作符還要簡(jiǎn)單。例如:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        GlobalScope.launch(Dispatchers.Main) {
            Log.v("wuyue", "time 1==" + System.currentTimeMillis())
            val sum = withContext(Dispatchers.IO) {
                val requestA = async { requestA() }
                val requestB = async { requestB() }
                requestA.await() +"_____" +requestB.await()
            }
            Log.v("wuyue", "time 2==" + System.currentTimeMillis() + " get sum=" + sum)
        }
    }

    /**
     * 3s以后 才拿到請(qǐng)求結(jié)果 IQOO
     */
    fun requestA(): String {
        sleep(3 * 1000)
        Log.v("wuyue", "requestA in " + Thread.currentThread().name)
        return "IQOO"
    }

    /**
     * 5秒以后拿到請(qǐng)求結(jié)果 B
     */
    fun requestB(): String {
        sleep(5 * 1000)
        Log.v("wuyue", "requestB in " + Thread.currentThread().name)
        return "X27"
    }

}

Kotlin的協(xié)程和java線程性能的對(duì)比

可以看出來,我們的2個(gè)請(qǐng)求分別在不一樣的Thread中完成,并且回調(diào)到主線程的時(shí)機(jī)也差不多花了5s的時(shí)間,證明這2個(gè)request是并行請(qǐng)求的。

十、總結(jié)

  1.  Kotlin-JVM中所謂的協(xié)程是假協(xié)程,本質(zhì)上還是一套基于原生Java Thread API 的封裝。和Go中的協(xié)程完全不是一個(gè)東西,不要混淆,更談不上什么性能更好。

  2.   Kotlin-JVM中所謂的協(xié)程掛起,就是開啟了一個(gè)子線程去執(zhí)行任務(wù)(不會(huì)阻塞原先Thread的執(zhí)行,要理解對(duì)于CPU來說,在宏觀上每個(gè)線程得到執(zhí)行的概率都是相等的),僅此而已,沒有什么其他高深的東西。

  3.   Kotlin-Native是有機(jī)會(huì)實(shí)現(xiàn)完整真協(xié)程方案的。雖然我個(gè)人不認(rèn)為JB TEAM 在這方面能比Go做的更好,所以這個(gè)項(xiàng)目意義并不是很大。

  4.   Kotlin-JVM中的協(xié)程最大的價(jià)值是寫起來比RxJava的線程切換還要方便。幾乎就是用阻塞的寫法來完成非阻塞的任務(wù)。

  5.   對(duì)于Java來說,不管你用什么方法,只要你沒有魔改JVM,那么最終你代碼里start幾個(gè)線程,操作系統(tǒng)就會(huì)創(chuàng)建幾個(gè)線程,是1比1的關(guān)系。

  6.   OpenJDK正在做JVM的協(xié)程實(shí)現(xiàn),項(xiàng)目名稱為loom,有興趣的同學(xué)可以查看對(duì)應(yīng)資料。

  7.   Kotlin官網(wǎng)中那個(gè)創(chuàng)建10w個(gè)Kotlin協(xié)程沒有oom的例子其實(shí)有誤導(dǎo)性,本質(zhì)上那10w個(gè)Kotlin協(xié)程就是10w個(gè)并發(fā)任務(wù)僅此而已,他下面運(yùn)行的就是一個(gè)單線程的線程池。你往一個(gè)線程池里面丟多少個(gè)任務(wù)都不會(huì)OOM的(前提是你的線程池創(chuàng)建的時(shí)候設(shè)定了對(duì)應(yīng)的拒絕策略,否則***隊(duì)列下,任務(wù)過多一定會(huì)OOM),因?yàn)樵谶\(yùn)行的始終是那幾個(gè)線程。

看完上述內(nèi)容,你們對(duì)Kotlin的協(xié)程有進(jìn)一步的了解嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀。

文章標(biāo)題:Kotlin的協(xié)程和java線程性能的對(duì)比
文章URL:http://aaarwkj.com/article16/pegigg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制網(wǎng)站、網(wǎng)站收錄品牌網(wǎng)站建設(shè)、軟件開發(fā)外貿(mào)網(wǎng)站建設(shè)、ChatGPT

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)
99久久精品人妻一区| 欧美日韩一区二区黄色| 欧美视频亚洲视频自拍视频| 精品欧美熟妇高潮喷水特黄 | 精品视频一区二区三区在线观看| 一区二区三区国产激情| 性感美女国产精品一区二区| 亚洲国产高清国产拍精品| 97免费公开在线观看| 国产高跟丝袜女王调教| 久久re这里只有精品6| 福利在线视频一区二区| 久久99精品人妻一区二区三区| 国产91日韩欧美在线观看| 青青草原精品资源视频| 日韩三级黄片在线观看| 日本一区二区三区高清在线| 最新日韩精品电影在线网| 日韩免费精品一区二区| 成人免费在线观看午夜| 中文字幕一区二区三区精彩视频| 亚洲欧美综合一区二区三区| 久久久久久精品国产毛片| 亚洲国产日韩精品av| 久久精品免成人费电影| 亚洲欧美日韩不卡视频| 国产精品视频一区二区噜| 国产三级一区二区不卡| 欧美国产日韩一区二区三区视频| 最近更新中文字幕不卡在线| 亚洲日本日本午夜精品| 日韩欧美啪啪一区二区| av中文字幕国产精品| 国产亚洲欧美日韩中文字幕| 欧美亚洲另类不卡在线| 日韩免费色视频一区| 日本高清免费中文字幕| 欧洲女人av天堂精品| 国产偷国产偷亚洲综合av| 国产精品一区二区三区 在线| 国产精品一区二区熟女|