scala:我们能不能像goroutine那样放弃/恢复演员



我正在学习标量。我很困惑演员和goroutine之间的区别。

众所周知,golang的并发单元是goroutine,在我看来,并发模型非常特殊和优雅:

  • CPU绑定任务

运行时调度程序会尽最大努力抢占长时间运行的协程,例如在函数调用时检查抢占,这样长时间运行协程就不会占用系统线程太长的

  • 事件驱动调用

例如,在Linux上,可以由epoll管理的所有类型的事件,例如套接字连接,都会产生goroutine,并在稍后调用完成时恢复它。当goroutine产生时,保持线程将被释放以处理下一个准备好的goroutine

  • cgo调用

这样的调用将只占用一个系统线程,直到调用返回。

如何在scala-actor中处理所有这些类型的调用?

scala重用并依赖JDK来访问低级系统调用,对吧?例如网络插座。一些高级库也在scala中被重用,例如JDBC。Java的并发模型是线程(系统线程),Java中的所有调用都会阻塞线程,直到调用返回。那么如何将它们封装在actor中呢?演员的表演和goroutine不同吗?

期待任何专业的答案!谢谢

编辑:

我搜索了一些文件,我想答案可能是:

  • CPU绑定任务

scala 中未提供抢占

  • 事件驱动调用

由于Akka被集成到scala中,所以要么使用Akka异步封装库(例如Akka-TCP),要么使用future?

  • cgo调用

???

我更改了这篇文章的标题。我已经理解actor和goroutine之间的风格差异,我只关心如何在actor中处理不同类型的调用,就像gorotuine一样。

编辑:

对不起,我终于发现我的问题是什么:

我们能像goroutine那样放弃/恢复演员吗

或者演员只是一个从开始到结束都应该运行的预定计算片段?即整个消息处理不能被中断。

由于Java中的线程模型,我认为它缺乏对基于协程的阻塞调用的低级支持,对吧?例如套接字读取,如果块,则产生协程,当新的数据被读取时,恢复协程;虽然它对程序员来说是透明的,但你只需要编写socket.read()。众所周知,在Java中,整个过程都是基于系统线程的,传统的方式就像C.一样

如果您只想知道如何处理IO调用,那么Future在scala中被认为更惯用。

当你有一个层次模型,或者你想要任何复杂的故障恢复机制时,Akka是很好的,但如果你只想做IO,Future就足够了,而且简单得多。

此外,IO调用可以是阻塞的,也可以是非阻塞的(在线程级别),您需要单独处理它。幸运的是,它和一样简单

Future {
// non-blocking IO call
} 
import scala.concurrent.blocking
Future {
blocking {
... some blocking IO call
}
}

如果您需要执行大量IO阻塞调用,请使用单独的ExecutionContext

不要将CPU绑定的任务封装在Future中,CPU绑定意味着您的程序不会因为Future而受益。如果您需要Future来匹配接口,请使用

Future.successful {
// computation
}

我从中学到了这些细节

  1. https://github.com/alexandru/scala-best-practices/blob/master/sections/4-concurrency-parallelism.md
  2. http://docs.scala-lang.org/overviews/core/futures.html

编辑1:问题已更新,此编辑尝试回答新问题

:我们可以让位/恢复演员吗?

A:我不太确定我是否理解正确,我可以知道你为什么要放弃并恢复一个演员吗?您似乎希望控制运行时的低级处理细节,我认为这对于actor来说是无法实现的。

Actor是被动的,意味着每当你向它发送消息时,它都会做一些事情,仅此而已,你无法控制事情的执行方式,同一个Actor甚至可能在不同的线程上运行。

通常,如果我们需要异步操作,我们会将操作包装在Future中,但future不会自动使问题消失,如果您包装在future中的操作阻塞了线程,它仍然会阻塞,但包装在future中会使您的代码异步,即,可以运行下一行代码,而无需等待上一个操作返回。

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import java.lang.Thread
Future {
Thread.sleep(1000)
println("Woke up")
}
println("Sleeping")

结果将是

Sleeping
Woke up

最新更新