使用Actor而不是“同步”

每次我读到在Scala中使用时,作者通常会提到应该使用Actor(例如)。虽然我大致了解Actor是如何工作的,但我真的希望看到Actor在一段代码中被用来替换Java的方法修饰符(我的意思是它的Scala等效物 - 块)的例子。例如,修改数据结构的内部结构会很高兴看到。synchronizedsynchronizedsynchronized

这是对演员的良好使用还是我被误导了?


答案 1

1) 概述

Scala Actor可以取代标准Java线程应用程序中的复杂业务逻辑,这些应用程序通常可以避免在复杂的多线程系统上工作的开发人员。

请考虑以下 java 代码片段,人们可能会在一个简单的线程化应用程序中看到这些代码片段(此代码正在等待异步请求完成)。

myAsyncRequest.startCalculation(); 
while(notDone)
   myAsyncRequest.checkIfDone();
   Thread.sleep(1000); 
System.out.println("Done ! Value is : " + myAsyncRequest.getCalculationValue());

要查看使用Scala的更高级别的并发模型直接替换此类代码,请查看这篇文章:Scala程序在执行和完成所有Scala Actor消息之前退出。如何阻止这种情况?

2)现在:回到代码snpipet---这里有一些明显的问题,让我们快速浏览一下:

  • 该代码将“监视”计算执行的逻辑与计算结果的处理耦合。
  • 代码中嵌入了启发式方法(Thread.sleep(1000)),它们没有明确的逻辑理由(为什么要等一下?为什么不等待3秒?),从而为代码块添加不必要的逻辑。
  • 它不会扩展 - 如果我运行1000个客户端,并且每个客户端都在不断检查结果,我可能会无缘无故地生成一些非常丑陋的流量---。

scala如何修改这个范式?

  • Scala演员可以返回“期货”

这些概括了这样一种期望,即你希望演员做的“事情”很快就会完成。scala“future”取代了这个java结构:它使“显式”的事实,我的while循环“期望”在不久的将来发生某些事情,并且之后有一个动作要做。

  • Scala actor可以传递“消息”

虽然我正在“等待”(在上面的while循环中)完成,但很明显,另一种实现方法是计算对象在完成时简单地“告诉我”。消息传递可以实现这一点,但有些复杂,并导致某些java实现中无法追踪,不可读的代码。由于 scala 以一种直接设计用于适应并发工作负载的方式抽象了这个概念,因此消息传递设计模式现在可以以一种不太复杂的方式实现,从而将“等待”的逻辑与处理逻辑分离。

3)简短的回答:一般来说,scala API是为在更高抽象级别上编码并发逻辑而构建的,因此您的并发代码是声明性的,而不是在实现细节上混淆。

4)同步:一个较低级别的概念,虽然是必不可少的,但可能会使我们的代码复杂化。

同步是较低级别的多线程编程的产物。通过提供最常见的并行编程范式的更高级别抽象,Scala使这种特定的结构在许多最常见的并发编程用户情况下变得不必要。事实上,如今,即使是java也这样做:)java.util.concurrent 包为我们提供了原子数据类型和数据结构,从而无需将简单操作包装在“同步”块中。但是,标准Java不支持“Actor”和“Futures”的更高层次的概念,这些概念可以有效地管理和协调,而无需手动管理同步的方法调用或对象修改。


答案 2

Actor保证一次只处理一条消息,这样就不会有两个线程访问任何实例成员 - 因此不需要使用同步


推荐