協(xié)程

協(xié)程

1.Kotlin 中的協(xié)程是什么?

簡單理解:一般程序會有一個主進程链韭,主進程中可能含有多個線程排霉。而協(xié)程窍株,是線程中的,也就是說一個線程中可能包含多個協(xié)程攻柠,協(xié)程與協(xié)程之間是可以嵌套的球订。

image

2.有什么作用?

當線程要執(zhí)行可能會阻塞的任務時瑰钮,一般情況下會開啟一個子線程來完成冒滩,如果阻塞任務過多,就需要開啟多個子線程(線程池)浪谴,協(xié)程可以幫助我們完成的是开睡,將可能會阻塞的任務放在線程的協(xié)程中來完成,多個任務就創(chuàng)建多個協(xié)程苟耻。線程直接維持數(shù)據(jù)準確性需要消耗很多資源篇恒,而協(xié)程消耗的會少很多。

注:協(xié)程是可以直接運行在進程中的凶杖,不是一定要依賴于線程胁艰,只不過現(xiàn)在支持協(xié)程的 Kotlin Python Go 等語言都會以主線程的方式開啟程序的運行。

總結(jié):通過提升 CPU 利用率官卡,減少線程切換進而提升程序運行效率蝗茁。

3.協(xié)程的特性

  • 可控制:協(xié)程能做到可被控制的發(fā)起子任務(協(xié)程的啟動和停止都由代碼控制,不像 java)
  • 輕量級:協(xié)程非常小寻咒,占用資源比線程還少
  • 語法糖:使多任務或多線程切換不再使用回調(diào)語法

二哮翘、協(xié)程庫

kotlinx.coroutines
compile "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.22.5"

1.使用 idea 創(chuàng)建 gradle 工程

image

2.在Kotlin中啟動協(xié)程

  • runBlocking: T
    • 用于執(zhí)行協(xié)程任務,通常只用于啟動最外層的協(xié)程(線程到協(xié)程的調(diào)度)
  • launch: Job
    • 用于執(zhí)行協(xié)程任務毛秘,返回的 Job 是一個接口引用
  • async/await: Deferred
    • 用于執(zhí)行協(xié)程任務饭寺,并得到執(zhí)行結(jié)果
import kotlinx.coroutines.experimental.async
import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking

/**
 * main=runBlocking
 * 表示主線程開始后直接就開啟了一個協(xié)程
 * 在協(xié)程中執(zhí)行任務
 */
fun main(args: Array<String>) = runBlocking {

    val job = launch {
        repeat(10) { I ->

            println("掛起中------$I")
            //每次循環(huán)阻课,暫停1秒
            delay(1000L)

        }
    }

    val job2 = async {
        //掛起5秒
        delay(5000L)
        //使用注解標注此處返回的是 async 的閉包
        return@async "我是 async 返回的內(nèi)容"
    }

    /**
     * await 是一個阻塞式方法
     * 會將主線程停在這里
     * 當 job2 掛起5秒結(jié)束,返回內(nèi)容
     * await 接受到內(nèi)容艰匙,主線程才繼續(xù)向下執(zhí)行-->開始等待
     */
    println("job2 返回的內(nèi)容:${job2.await()}")
    println("主線程開始等待-----")
    delay(3000L)
    println("主線程等待結(jié)束-----取消launch開啟的協(xié)程")
    job.cancel()//協(xié)程的啟動和停止都是代碼可控的

    println("主線程執(zhí)行完畢限煞,即將推出-----")

}
image

三、協(xié)程的啟動參數(shù)

以下是 launch 的參數(shù)列表员凝,runBlocking署驻、async 與 launch 參數(shù)列表是差不多的

  • context: CoroutineContext = DefaultDispatcher
    • 當前 協(xié)程 的上下文,用于在 協(xié)程 與 協(xié)程 之間參數(shù)傳遞
    • 可以用于聲明當前 協(xié)程 在哪一個線程中聲明健霹,以及當前 協(xié)程 被中斷后旺上,在哪一個線程中恢復它
    • DefaultDispatcher 就是一個默認的調(diào)度器,當前哪個線程在運行糖埋,就直接取哪個線程
  • start: CoroutineStart = CoroutineStart.DEFAULT
    • 協(xié)程 的啟動參數(shù)宣吱,表示已哪種方式啟動
    • CoroutineStart.DEFAULT 默認的啟動方式,表示當前線程什么時候有空瞳别,就什么時候啟動
    • 可選參數(shù):LAZY征候,如果沒有手動調(diào)用 job 對象的 start() 或 join() 方法的話,那么該 協(xié)程 是不會被啟動的
    • 可選參數(shù):ATOMIC祟敛,將 協(xié)程 以一個原子性質(zhì)的形式的啟動疤坝,如果聲明此參數(shù),則協(xié)程是不可以 cancel 的
    • 可選參數(shù):UNDISPATCHED馆铁,未定義卒煞,通常用于自定義的啟動方式,如果未自定義叼架,則與 DEFAULT 啟動方式一致。
  • parent: Job? = null
    • 表示在當前 協(xié)程 閉包的外層的 job衣撬,一般情況下使用不到
  • block: suspend CoroutineScope.() -> Unit
    • 協(xié)程真正要去執(zhí)行的內(nèi)容

四乖订、協(xié)程的語法糖

允許我們使用同步的代碼格式,發(fā)起一次異步的網(wǎng)絡請求

package zyf.com.kotlin_

import android.os.AsyncTask
import kotlinx.coroutines.experimental.CoroutineDispatcher
import kotlinx.coroutines.experimental.Runnable
import kotlin.coroutines.experimental.CoroutineContext

/**
 * create by zyf on 2018/9/17 下午4:58
 */
object AndroidCommonPool: CoroutineDispatcher(){
    override fun dispatch(context: CoroutineContext, block: Runnable) {
        //使用android官方提供的線程池來執(zhí)行任務
        AsyncTask.THREAD_POOL_EXECUTOR.execute(block)
    }
}
package zyf.com.kotlin_

import android.widget.TextView
import kotlinx.coroutines.experimental.android.UI
import kotlinx.coroutines.experimental.async
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking
import okhttp3.OkHttpClient
import okhttp3.Request

/**
 * create by zyf on 2018/9/17 下午4:46
 */
private val mOkHttpClient= OkHttpClient()
private val mRequest=Request.Builder().url("https://www.baidu.com").get().build()

fun ktGet(textView: TextView) = runBlocking{

    launch(UI) {
        //傳入的AndroidCommonPool表示 async 開啟的這個協(xié)程具练,允許在 AndroidCommonPool 提供的線程中
        textView.text = async(AndroidCommonPool) {
            mOkHttpClient.newCall(mRequest).execute().body()?.string()
        }.await()
    }


}

package zyf.com.kotlin_

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)


    }

    fun java(v:View){

    }

    fun kotlin(v:View){
        ktGet(showTv)
    }
}

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <TextView
                android:id="@+id/showTv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />

            <Button
                android:id="@+id/javaBtn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Java獲取網(wǎng)絡數(shù)據(jù)"/>

            <Button
                android:id="@+id/kotlinBtn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Kotlin獲取網(wǎng)絡數(shù)據(jù)"
                android:onClick="kotlin"/>

            <Button
                android:id="@+id/cleanBtn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="清除"/>
        </LinearLayout>
    </ScrollView>

</android.support.constraint.ConstraintLayout>
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末乍构,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子扛点,更是在濱河造成了極大的恐慌哥遮,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件陵究,死亡現(xiàn)場離奇詭異眠饮,居然都是意外死亡,警方通過查閱死者的電腦和手機铜邮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進店門仪召,熙熙樓的掌柜王于貴愁眉苦臉地迎上來寨蹋,“玉大人,你說我怎么就攤上這事扔茅∫丫桑” “怎么了?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵召娜,是天一觀的道長运褪。 經(jīng)常有香客問我,道長玖瘸,這世上最難降的妖魔是什么秸讹? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮店读,結(jié)果婚禮上嗦枢,老公的妹妹穿的比我還像新娘。我一直安慰自己屯断,他們只是感情好文虏,可當我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著殖演,像睡著了一般氧秘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上趴久,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天丸相,我揣著相機與錄音,去河邊找鬼彼棍。 笑死灭忠,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的座硕。 我是一名探鬼主播弛作,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼华匾!你這毒婦竟也來了映琳?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤蜘拉,失蹤者是張志新(化名)和其女友劉穎萨西,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體旭旭,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡谎脯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了您机。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片穿肄。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡年局,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出咸产,到底是詐尸還是另有隱情矢否,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布脑溢,位于F島的核電站僵朗,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏屑彻。R本人自食惡果不足惜验庙,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望社牲。 院中可真熱鬧粪薛,春花似錦、人聲如沸搏恤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽熟空。三九已至藤巢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間息罗,已是汗流浹背掂咒。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留迈喉,地道東北人绍刮。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像挨摸,于是被迫代替她去往敵國和親录淡。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,543評論 2 349

推薦閱讀更多精彩內(nèi)容