kotlin并发性

kotlin并发性

新开始读G. Blake Meike写的"Android Concurrency",到目前为止我非常推荐这本伟大的书,

它包含了许多关于不同的Android并发机制如何工作的深刻见解,当您更喜欢一种实现方式而不是另一种实现方式时,如何获得最好的方法。

我决定学习书中的例子,并且重写这些例子。由于我非常地热爱kotlin,我觉得把这些例子用kotlin实现是个不错的主意。

在Android Concurrency书的第一章,作者使用java中最基本的并发语法,因此现在我开始使用kotlin书写这些代码例子,我非常惊奇的发现:

在kotlin中没有synchronized 关键字

在kotlin中没有volatile 关键字

kotlin中的Any和java中的Object相似,但是没有wait(), notify() 和 notifyAll() 三个方法

那么并发是如何在kotlin中工作的呢?这个问题已经在kotlin forum中被问到了。如下是kotlin项目leader Andrey Breslav的回答:

Kotlin故意没有构建语言的并发性。我们认为这应该由libraries来处理。

尽管kotlin没有把并发性内置在语音中,但是仍然提供了很多低语言的并发语法。现在,让我们来看看这些语法。

Creating Threads

在java中有两种方法创建一个线程:

1:扩展Thread类

2:实例化Thread类并且通过构造函数传入一个Runnable

因为你能够kotlin中简单的使用java 类,上述两种方法也可以很好的起作用。

下面展示如下子类化Thread:

object : Thread() {
     override fun run() { 
         println("running from Thread:${Thread.currentThread()}")
     }
}.start()

这部分代码使用到了kotlin的Object 表达式创建匿名类,并且重写了run()方法。此处将会演示如何传入一个Runnable对象来创建Thread的实例:

Thread({
     println("running from lambda:${Thread.currentThread()}")
}).start()

在这你并没有看到Runnable对象,在kotlin中你能够很容易的使用lambda表达式。是否还有更好的方法呢?当然!下面将会演示如果使用kotlin风格实例化并且启动一个线程:

thread(start=true) {
    println("running from thread():${Thread.currentThread()}")
}

很简洁,不是么?我们正在使用thread()方法,它会神奇地隐藏所有的样板代码。事实上,下面将展示完成的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
}

它只是一个非常方便的包装函数,使用起来很方便。

Synchronized Methods and Blocks

在kotlin中,synchronized不是一个关键字,使用@Synchronized注解。

在kotlin中一个synchronized方法的声明看起来如下所示:

@Synchronized fun synchronizedMethod() {
    println("inside a synchronized method:${Thread.currentThread()}")
}

这个注解和Java中的synchronized有同样的效果:它将把JVM方法标记为同步。对应同步代码块,你不得不使用synchronized()方法,这将会使用一个lock作为一个参数:

fun methodWithSynchronizedBlock() {
    println("outside of a synchronized block:${Thread.currentThread()}")
    synchronized(this) {
         println("inside a synchronized block:${Thread.currentThread()}")
    }
}

代码的外观和行为与Java变量非常相似。

Volatile Fields

同样地,在kotlin中没有volatile关键字,但是有@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支持字段标记为volatile。

wait(), notify() and notifyAll()

在kotlin中,每一个类都是从Any继承过来的,但是Any并没有声明wait(),notify()和notifyAll()方法,这就意味着,你不能在kotlin类中调用这些方法。但是你仍然能够使用java.lang.Object的实例作为lock,并且调用相关的方法。下面将会展示一个使用Objec做为lock解决生产者和消费者的问题,

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(译者注:不是很明白)

事实是如果在你的代码中使用如此low-level constructs,看起来正在做一些错误的事情了。如今无论是在java中还是kotlin中都有很多高级的并发机制满足每一个需求,在Stackoverflow上面有一个非常棒的回答,并且提供了一系列可用的工具来写并发代码。

文章中的代码已经发布到GitHub,请参考。

Conclusion

尽快在项目中不会被频繁地使用到,但是了解和理解基础的知识还是比较重要的。最终发现在kotlin和java还是有一些不同的地方,但是主要的机制是一样的。请记住,kotlin和java的交互时候非常棒的,所以如果kotlin 没有counterparts,你就可以依赖Java类。玩得开心!

原文地址链接:https://blog.egorand.me/concurrency-primitives-in-kotlin/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,486评论 25 707
  • 本文出自 Eddy Wiki ,转载请注明出处:http://eddy.wiki/interview-java.h...
    eddy_wiki阅读 2,054评论 0 14
  • 年初的预想是一天记一篇,坚持了四天。不是我军不努力,无奈考试周有高达。 一学期算下来,诚心正意地,把驳杂的心绪放到...
    秋库里阅读 383评论 0 0
  • 世界上有很多职业,大多数是人们非常熟悉的,比如老师,医生,律师,警察。这些寻常的职业存在于我们日常的生活中,无人不...
    画歌Echo阅读 753评论 4 9
  • 婚姻好的时候很幸福,不好的时候也挺烦人!不好的时候就多想想好的时候吧!于是我写下我们好的时候,等到不好的时候再翻出...
    奕橙阅读 565评论 2 6