kotlin并發(fā)性
新開始讀G. Blake Meike寫的"Android Concurrency",到目前為止我非常推薦這本偉大的書允青,
它包含了許多關(guān)于不同的Android并發(fā)機(jī)制如何工作的深刻見解萌衬,當(dāng)您更喜歡一種實(shí)現(xiàn)方式而不是另一種實(shí)現(xiàn)方式時(shí)姜盈,如何獲得最好的方法径缅。
我決定學(xué)習(xí)書中的例子,并且重寫這些例子姜胖。由于我非常地?zé)釔踜otlin誉帅,我覺得把這些例子用kotlin實(shí)現(xiàn)是個不錯的主意。
在Android Concurrency書的第一章右莱,作者使用java中最基本的并發(fā)語法蚜锨,因此現(xiàn)在我開始使用kotlin書寫這些代碼例子,我非常驚奇的發(fā)現(xiàn):
在kotlin中沒有synchronized 關(guān)鍵字
在kotlin中沒有volatile 關(guān)鍵字
kotlin中的Any和java中的Object相似慢蜓,但是沒有wait(), notify() 和 notifyAll() 三個方法
那么并發(fā)是如何在kotlin中工作的呢亚再?這個問題已經(jīng)在kotlin forum中被問到了。如下是kotlin項(xiàng)目leader Andrey Breslav的回答:
Kotlin故意沒有構(gòu)建語言的并發(fā)性晨抡。我們認(rèn)為這應(yīng)該由libraries來處理氛悬。
盡管kotlin沒有把并發(fā)性內(nèi)置在語音中,但是仍然提供了很多低語言的并發(fā)語法≡胖現(xiàn)在如捅,讓我們來看看這些語法。
Creating Threads
在java中有兩種方法創(chuàng)建一個線程:
1:擴(kuò)展Thread類
2:實(shí)例化Thread類并且通過構(gòu)造函數(shù)傳入一個Runnable
因?yàn)槟隳軌騥otlin中簡單的使用java 類调煎,上述兩種方法也可以很好的起作用镜遣。
下面展示如下子類化Thread:
object : Thread() { override fun run() { println("running from Thread:${Thread.currentThread()}") } }.start()
這部分代碼使用到了kotlin的Object 表達(dá)式創(chuàng)建匿名類,并且重寫了run()方法士袄。此處將會演示如何傳入一個Runnable對象來創(chuàng)建Thread的實(shí)例:
Thread({ println("running from lambda:${Thread.currentThread()}") }).start()
在這你并沒有看到Runnable對象悲关,在kotlin中你能夠很容易的使用lambda表達(dá)式谎僻。是否還有更好的方法呢?當(dāng)然寓辱!下面將會演示如果使用kotlin風(fēng)格實(shí)例化并且啟動一個線程:
thread(start=true) { println("running from thread():${Thread.currentThread()}") }
很簡潔戈稿,不是么?我們正在使用thread()方法讶舰,它會神奇地隱藏所有的樣板代碼。事實(shí)上需了,下面將展示完成的thread()方法:
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 }
它只是一個非常方便的包裝函數(shù)跳昼,使用起來很方便。
Synchronized Methods and Blocks
在kotlin中肋乍,synchronized不是一個關(guān)鍵字鹅颊,使用@Synchronized注解。
在kotlin中一個synchronized方法的聲明看起來如下所示:
@Synchronized fun synchronizedMethod() { println("inside a synchronized method:${Thread.currentThread()}") }
這個注解和Java中的synchronized有同樣的效果:它將把JVM方法標(biāo)記為同步墓造。對應(yīng)同步代碼塊堪伍,你不得不使用synchronized()方法,這將會使用一個lock作為一個參數(shù):
fun methodWithSynchronizedBlock() { println("outside of a synchronized block:${Thread.currentThread()}") synchronized(this) { println("inside a synchronized block:${Thread.currentThread()}") } }
代碼的外觀和行為與Java變量非常相似觅闽。
Volatile Fields
同樣地帝雇,在kotlin中沒有volatile關(guān)鍵字,但是有@Volatile注解蛉拙,
@Volatile private var running = false fun start() { running = true thread(start = true) { while(running) { println("Still running:${Thread.currentThread()}") } } } fun stop() { running = false println("Stopped:${Thread.currentThread()}") }
和@Synchronized是相似的尸闸,@Volatile將把JVM支持字段標(biāo)記為volatile。
wait(), notify() and notifyAll()
在kotlin中孕锄,每一個類都是從Any繼承過來的吮廉,但是Any并沒有聲明wait(),notify()和notifyAll()方法,這就意味著畸肆,你不能在kotlin類中調(diào)用這些方法宦芦。但是你仍然能夠使用java.lang.Object的實(shí)例作為lock,并且調(diào)用相關(guān)的方法轴脐。下面將會展示一個使用Objec做為lock解決生產(chǎn)者和消費(fèi)者的問題调卑,
private val lock = java.lang.Object() fun produce() = synchronized(lock) { ? ? while(items>=maxItems) { ? ? ? ? lock.wait() ? ? } ? ? Thread.sleep(rand.nextInt(100).toLong()) ? ? items++ ? ? println("Produced, count is$items:${Thread.currentThread()}") ? ? lock.notifyAll() } fun consume() = synchronized(lock) { while(items<=0) { lock.wait() } Thread.sleep(rand.nextInt(100).toLong()) items-- println("Consumed, count is$items:${Thread.currentThread()}") lock.notifyAll() }
Does it look hacky? Well, it is(譯者注:不是很明白)
事實(shí)是如果在你的代碼中使用如此low-level constructs,看起來正在做一些錯誤的事情了大咱。如今無論是在java中還是kotlin中都有很多高級的并發(fā)機(jī)制滿足每一個需求令野,在Stackoverflow上面有一個非常棒的回答,并且提供了一系列可用的工具來寫并發(fā)代碼徽级。
文章中的代碼已經(jīng)發(fā)布到GitHub气破,請參考。
Conclusion
盡快在項(xiàng)目中不會被頻繁地使用到餐抢,但是了解和理解基礎(chǔ)的知識還是比較重要的现使。最終發(fā)現(xiàn)在kotlin和java還是有一些不同的地方低匙,但是主要的機(jī)制是一樣的。請記住碳锈,kotlin和java的交互時(shí)候非常棒的顽冶,所以如果kotlin 沒有counterparts,你就可以依賴Java類售碳。玩得開心!
原文地址鏈接:https://blog.egorand.me/concurrency-primitives-in-kotlin/