我正在学习scala。我对actor和goroutine之间的区别非常困惑。
众所周知,golang的并发单元是goroutine,并且我认为并发模型非常特殊和优雅:
运行时调度程序将尽最大努力抢占长时间运行的协同程序,例如:检查函数调用的抢占,以便长时间运行的协程不会占用系统线程太长
例如,在Linux上,可以由epoll管理的所有类型的事件,例如,套接字连接,将产生goroutine并在稍后调用完成后恢复它。当goroutine产生时,保持线程将被释放以处理下一个准备好的goroutine
这些调用将专门占用一个系统线程,直到调用返回。
如何在scala actor中处理所有这些类型的调用?
scala重用并依赖于JDK来访问低级系统调用,对吧?例如网络套接字。并且一些高级库也在scala中重用,例如JDBC。 Java的并发模型是线程(系统线程),Java中的所有调用都会在调用返回之前阻塞线程。那么如何将它们封装在actor中呢?演员表演与goroutine不同吗?
期待任何专业的答案!谢谢!
修改
我搜索了一些文件,我想答案可能是:
scala中没有提供抢占
由于Akka被集成到scala中,所以要么使用Akka异步包装库(例如Akka TCP)还是使用未来?
???
我更改了这篇文章的标题。我已经理解了actor和goroutine之间的风格区别,我只关心如何在actor中处理不同类型的调用,就像gorotuine一样。
修改
抱歉,最后我发现了我的问题:
我们可以像goroutine那样产生/恢复演员吗?
或者演员只是一个应该从头到尾运行的预定计算部分?即整个消息处理无法中断。
由于Java中的线程模型,我认为缺乏基于协同程序阻止调用的低级支持,对吧?例如socket读取,如果是块,则产生协程,当新数据读取时读取,恢复协程;虽然它对程序员来说是透明的,但你需要编写的只是socket.read()。众所周知,在Java中,整个过程基于系统线程,传统方式就像C。
答案 0 :(得分:2)
如果您只想知道如何处理IO调用,那么在Scala中,Future被认为更加惯用。
当你有一个层次模型,或者你想要任何复杂的故障恢复机制时,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
}
我从
了解了大部分细节问:我们可以屈服/恢复演员?
<强> A 强>: 我不太确定我是否理解正确,我可能知道你为什么要屈服并恢复一个演员? 您似乎希望控制运行时的低级处理细节,我认为对于actor 无法实现。
Actor是被动的,意味着每当你向它发送消息时它都会做某事,而这就是你无法控制事情的执行方式,同一个actor甚至可以在不同的线程上运行。
通常,如果我们需要异步操作,我们将操作包装在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