Kotlin禅与计算机程序设计艺术程序员

kotlin并发性

2017-05-24  本文已影响0人  甲乙丙丁你我他

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/

上一篇下一篇

猜你喜欢

热点阅读