Kotlin学习九:kotlin中的异步操作(wait(), notify() 和 notifyAll())

我(原作者)最近开始阅读G. Blake Meike的“Android Concurrency”,到目前为止,我可以强烈推荐这本伟大的书:它包含了很多洞察如何各种Android并发机制的工作,何时喜欢一种方法,以及如何获得最好的工具,在您的处置。我决定遵循代码示例,并在我的电脑上重新创建它们,并且由于我非常爱Kotlin,我认为这将是一个好主意,将示例转换为Kotlin在旅途中。当我开始重写Kotlin中的代码示例时,我非常惊讶地发现:

Kotlin中没有synchronized关键字
Kotlin中没有volatile关键字
Kotlin的Any类似于Java的Object,没有wait(),notify()和notifyAll()方法

那么并发如何在Kotlin中工作呢?这个问题已经在Kotlin论坛上提出,这里是来自Andrey Breslav,Kotlin项目负责人的回答:
Kotlin故意没有内置并发语言的构造。我们认为这应该由图书馆来处理。
虽然Kotlin没有这些东西内置的语言,它仍然提供了一堆低级并发工具。让我们来看看商店里有什么。

创建线程

有两种方法在Java中创建线程:扩展Thread类,或者实例化它并通过构造函数传递一个Runnable。 因为你可以很容易地在Kotlin中使用Java类,这两个解决方案都很好。 这里是你如何子类Thread:

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

此代码使用Kotlin的对象表达式创建一个匿名类并覆盖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不是Kotlin中的关键字,它替换为@Synchronizedannotation。 Kotlin中的同步方法的声明将如下所示:

ps:我是不太明白Kotlin开发团队的用意,把原来Java中的注解@Override变成了override关键字;又把synchronized关键字变成了注解@Synchronizedannotation;我只想说 what are you 弄啥嘞!?!

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

注释与Java的synchronized具有相同的效果:它会将JVM方法标记为同步。 对于同步块,你必须使用synchronized()函数,它使用锁作为参数:

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

代码看起来和行为非常类似于Java变体。

可变字段

同样的故事,Kotlin没有volatile关键字,但是有@Volatileannotation:

@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() 和 notifyAll()

Kotlin中的每个类都继承自Any,但Any不声明wait(),notify()和notifyAll(),这意味着这些方法不能在Kotlin类上调用。 但是你仍然可以使用java.lang.Object的一个实例作为锁,并调用它的方法。 这里是使用Object作为锁的生产者/消费者问题的解决方案:

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()
}

它看起来很黑吗? 好吧,是的。 真理是,如果你在代码中依赖这样的低级结构 - 很可能你做错了。 现在有很多高级并发机制用于Java和Kotlin的每一个目的。 这里有一个伟大的Stackoverflow答案,提供了可用于在Kotlin中编写并发代码的工具列表。

本文的所有代码示例都可以在GitHub上获取。

结论

虽然它们不常使用,但了解和了解基本的并发工具仍然很重要。 结果,这些工作在Kotlin有点不同在Java,但所有主要机制都支持。 并记住,Kotlin与Java非常好地交互,所以如果Kotlin对应的方法丢失,你可以依靠Java类。 玩的开心!

原文链接:https://blog.csdn.net/sergeycao/article/details/53894787

原文是译文,我就直接转过来了,有的词用的不像是正常的用语,可能部分是机器翻译的,能看懂就行了,懒得改了

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值