基礎執行緒
對於初次學習執行緒的人,可以想像成是一顆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()
}