Kotlin(四)掌握基礎知識:線程(Thread.kt)詳解

Kotlin(一)掌握基礎知識:數據、集合、庫函數
Kotlin(二)掌握基礎知識:字符串和異常處理
Kotlin(三)掌握基礎知識:類

  線程是每一種語音不可能繞開的知識點,這章我們就來仔細看下Kotlin中如何使用線程,我們仔細看下Thread.kt文件的實現

package kotlin.concurrent

public fun thread(
    start: Boolean = true,
    isDaemon: Boolean = false,
    contextClassLoader: ClassLoader? = null,
    name: String? = null,
    priority: Int = -1,
    block: () -> Unit
): Thread {
    val thread = object : Thread() {
        public override fun run() {
            block()
        }
    }
    if (isDaemon)
        thread.isDaemon = true
    if (priority > 0)
        thread.priority = priority
    if (name != null)
        thread.name = name
    if (contextClassLoader != null)
        thread.contextClassLoader = contextClassLoader
    if (start)
        thread.start()
    return thread
}

@kotlin.internal.InlineOnly
public inline fun <T : Any> ThreadLocal<T>.getOrSet(default: () -> T): T {
    return get() ?: default().also(this::set)
}

  在包kotlin.concurrent中定義了兩個方法

  1. thread
  2. getOrSet

  其中thread方法便是我們創建線程所需要用到的函數;這個函數有6個參數,分別表示:

  1. 第4行,start:默認爲true,表示立即運行
  2. 第5行,isDaemon: 默認爲false,表示不是守護線程
  3. 第6行,contextClassLoader: 表示在這個線程中加載類/資源的類加載器
  4. 第7行,name:表示線程的名字
  5. 第8行,priority:表示線程的優先級
  6. 第9行,block:表示線程運行的主函數體

   那thread函數返回類型是什麼?看下第10行,答案是Thread類,看下這個Thread的實現

public
class Thread implements Runnable

  原來Kotlin中的線程其內部實現也是java中的Thread,那麼他的線程的狀態,線程的終止等等肯定都符合java的標準了

從第11行到27行,就是thread方法的函數體了

   那第9行中的block既然表示線程運行的主函數體,那它是怎麼被執行的? 爲了知曉這個問題的答案,我們首先得了解lambdar表達式

  lambdar表達式一般當參數類型是一個函數的時候,就可以使用它來簡化代碼的編寫 (高階函數的含義爲:一個將另一個函數作爲參數或者返回值的函數)

其完整語法爲:

val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }

其含義爲:
定義一個變量sum,其類型是lambda表達式
位於->的左邊,(Int, Int)爲lambda表達式的參數,分別爲兩個整形,
位於->的右邊,Int表示lambda表達式的返回類型
{}表示lambda的函數體

  在kotlin中,如果參數如果函數的最後一個參數是函數,那麼作爲相應參數傳入的 lambda 表達式可以放在圓括號之外,我們稱之爲拖尾 lambda 表達式

val product = items.fold(1) { acc, e -> acc * e }

  在kotlin中,如果函數只有lambda表達式,則調用的時候,可以省略圓括號

val product = items.fold { acc, e -> acc * e }

  在kotlin中,如果lambda表達式只有一個參數,則可以使用it來代替該參數,並忽略->符號

    var lists = listOf("","s")
    lists.forEach { print(it) }
    /** 等價寫法 **/
    lists.forEach { it -> print(it) }

  lambda表達式語法如下

    1. 無參數
    val/var 變量名 = { 操作的代碼 }
    
    2. 有參數
    val/var 變量名 : (參數的類型,參數類型,...) -> 返回值類型 = {參數1,參數2... -> 操作參數的代碼 }
    當表達式的返回值類型可以由系統自己推導出來,則可以簡寫爲
    val/var 變量名 = { 參數1 : 類型,參數2 : 類型, ... -> 操作參數的代碼 }
    
    3. lambda表達式作爲函數中的參數
    fun say(a : Int, 參數名 : (參數1 : 類型,參數2 : 類型, ... ) -> 表達式返回類型){
        參數名()  調用該lambda表達式
    }

  lambda表達式實際用例:

package com.kotline.learning

    private fun say() {
        println("**say**")
    }

    private fun people(hello: () -> Unit) {
        hello()
    }

    private fun people(content: String, hello: () -> Unit) {
        println("**people**$content")
    }

    fun main (args: Array<String>): Unit{
        people{say()}
        people("content", { say() })
        people("content") { say() }
    }

第3行定義了一個函數say,沒有參數,沒有返回值/或者說返回值爲Unit
第7行定義了一個函數people,其參數爲hello,類型爲一個lambda表達式
第8行表示調用/執行這個lambda表達式
第11行定義了一個函數people,其參數爲content和hello,類型一個是字符串型,一個lambda表達式

綜上內容,當我們調用函數people的時候,就可以寫爲

/** 調用第7行的people方法 **/
people({say()})
因爲kotlin的提出原則,上面的代碼可以簡寫爲:
people(){say()}
也可以簡寫爲
people{say()}

  現在我們返回到線程方法thread的第六個參數:block

 block: () -> Unit

他表示一個lambda表示式,無參且返回類型爲Unit,調用函數的寫法爲:

 block()

所以在函數thread的函數體中,即第13行,run方法中會調用到block

  現在我們來看看如果通過thread方法來創建一個立即運行的線程

fun printJob() {
    println("**printJob**")
}

thread({
	printJob()
})
/**  可簡寫爲: **/

thread{
  printJob()
}

  通過對象表達式創建一個線程

    Thread(object: Runnable{
        override fun run() {
        }
    }).start();
/** IDE會提示修改爲lambda形式:**/
    Thread(Runnable {
        printJob() 
    }).start();

  繼承Thread類,非匿名內部類的方式實現

    var kotlinThread : KotlinThread = KotlinThread();
    kotlinThread.start();

	class KotlinThread : Thread() {
    	override fun run() {
        	super.run()
        	println("KotlinThread 開始運行")
    	}
	}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章