Thread與Lambda

      在〈Thread與Lambda〉中尚無留言

基礎執行緒

對於初次學習執行緒的人,可以想像成是一顆CPU,執行一支程式。若新增了另一個執行緒,等於再多加一顆CPU,執行另一支程式。此時二支程式同時執行,而達成多工的功能。

當然上述的說法其實是錯的,而且是大錯特錯。但對於第一次接觸執行緒的人,而以用此錯誤的觀念作為進入點。致於正確的觀念,待基本觀念建立後,再進行更深入的說明。

首先建立一個MyThread類別繼承Thread類別,然後將要執行的任務置於覆寫的 run() 方法中。主程式中產生MyThread物件,再對此物件下執 start()指令。

fun main(args:Array<String>){
var t1=MyThread()
var t2=MyThread()
t1.start()
t2.start()
println("主執行程死亡了")
}
class MyThread:Thread(){
override fun run() {
for (i in 1..100){
println("%s : %d".format(Thread.currentThread().name, i))
}
}
}

請注意,kotlin的Thread類別,其實就是Java的Thread,所以有如下幾個屬性
1. Thread.currentThread().name : 取得執行緒的名稱
2. Thread.currentThread().id : 取得執行緒id
3. Thread.sleep(millisecons) : 睡眠

Runnable介面

實作Runnable介面,然後於主程式產生Runnable物件r,接著再產生Thread物件,將r塞入t裏面

fun main(args:Array<String>){
var r=Job()
var t1=Thread(r)
t1.start()
}
class Job: Runnable{
override fun run() {
Thread.currentThread().id
for (i in 1..100){
println("%s : %d".format(Thread.currentThread().name, i))
}
}
}

SAM

SAM全名為Single Abstract Method。在一個介面中,如果只有一個抽像方法,就稱為SAM。

SAM在物件導向中,不僅是常常出現,而且是成千上萬的出現。為何有這個現像呢? 因為SAM是貫穿整個系統的全域資料型態,系統本來就有無數個共用的SAM,而且我們也可以自行創造新的SAM。這些SAM在任何地方都可以被參考,但必需強制實作其契約。

類別無Lambda

類別與介面,其實沒有Lambda。

使用Lambda取代SAM

在kotlin中,Lambda的設計,其實就是要取代SAM。先用Thread的例子作說明。

fun main(args:Array<String>) {
var t=Thread(Job())
t.start()
}
class Job : Runnable{
override fun run() {

}
}

上述先產生一個Thread物件t1,然後把要執行的工作塞入Runnable 物件 r。t1再吃進r物件。r 物件其實只是著重於一個型態為 ()->Unit 的函數。

使用匿名函數作說明

fun main(args:Array<String>) {
var t: Thread = Thread(
fun ():Unit{
for (i in (0..100)) {
println("${i}")
Thread.sleep(100)
}
}
)
t.start()
}

要記得匿名函數其實是包裝一個函數型物件,而上述的函數型態為 ()->Unit。這觀念就跟上面所講的Runnable是一模一樣。這也就是為什麼可以用匿名函數塞入Thread物件之中的原因。

Lambda簡化

即然匿名函數可以塞到Thread物件之中,那麼自然可以改成Lambda的方式加以簡化,如下。

fun main(args:Array<String>) {
var t=Thread(){ ->
for (i in (0..100)) {
println("${i}")
Thread.sleep(100)
}
}
t.start()
}

更精簡的Lambda

Lambda的函數如果只有一個或沒有參數,那麼就可以把 Thread的 “()” 拿掉。

fun main(args:Array<String>) {
var t=Thread{ ->
for (i in (0..100)) {
println("${i}")
Thread.sleep(100)
}
}
t.start()
}

無我(Lambda)的境界

即然連參數都沒有,那麼 “->”就直接也省了

fun main(args:Array<String>) {
var t=Thread{
for (i in (0..100)) {
println("${i}")
Thread.sleep(100)
}
}
t.start()
}

萬佛朝宗

最後連Thread物件都不給名字了,這個沒有名字的Thread物件,算是匿名物件了。

fun main(args:Array<String>) {
Thread{
for (i in (0..100)) {
println("${i}")
Thread.sleep(100)
}
}.start()
}

 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *