Akka 参与者与普通对象
来自一本关于使用akka actors的反应式应用程序的书: 由于系统组件仅在收到消息时才对其作出反应,因此系统可以使用可用的 线程来运行当前必须对消息刺激作出反应的应用程序部分。一直以来,, 当前未对消息做出反应的组件没有利用宝贵的CPU资源 但对于不是参与者的正常对象也可以这样说。他们只在被要求做某事时才使用线程。那么,参与者与普通对象有何不同呢?(对于“对象”,您通常应该将其理解为“大多数OO语言中实现和使用的对象”) 我认为说“对象只在被要求做某事时才使用线程”并不准确:更准确的说法是线程使用对象,而不是相反。但无论我们以何种方式看待消费箭头,都必须注意它是不受限制的:一个对象可以在给定的时间点消费/被任意多个线程消费,一个线程可以在给定的时间点消费/被任意多个对象消费 考虑以下Scala代码:Akka 参与者与普通对象,akka,actor,Akka,Actor,来自一本关于使用akka actors的反应式应用程序的书: 由于系统组件仅在收到消息时才对其作出反应,因此系统可以使用可用的 线程来运行当前必须对消息刺激作出反应的应用程序部分。一直以来,, 当前未对消息做出反应的组件没有利用宝贵的CPU资源 但对于不是参与者的正常对象也可以这样说。他们只在被要求做某事时才使用线程。那么,参与者与普通对象有何不同呢?(对于“对象”,您通常应该将其理解为“大多数OO语言中实现和使用的对象”) 我认为说“对象只在被要求做某事时才使用线程”并不准确:更准确的说法是线
class A(private var b: B) {
def doSomethingWithB(): Unit = {
b.doSomething()
}
}
class B(private var x: Int) {
def doSomething(): Unit = {
x += 1
}
}
def foo(a: A): Unit = {
// yadda yadda yadda
a.doSomethingWithB()
}
线程通过调用doSomethingWithB
进入foo
并使用A
。当仍在使用a
时,它通过调用doSomething
来使用a.b
。它停止消费a.b
,然后停止消费a
对于actor系统,这两个1:N基数最多为1:1
显然,我们可以使对象实现具有类似于参与者的约束:如果使用对象的每个公共方法都需要获得锁,那么一个对象最多只能使用一个线程。同时,对于第二个约束,我们可以通过以下方式进行限制:
// simplified without references to things like ExecutionContexts
class A(...) {
def doSomethingWithB(): Future[Unit] = {
Future.successful(b).flatMap(_.doSomething())
}
}
class B(...) {
def doSomething(): Future[Unit] = {
x += 1
Future.successful(())
}
}
def foo(a: A): Future[Unit] = {
a.doSomethingWithB()
}
现在,当调用doSomethingWithB
时,调用线程(通常)不会消耗a.b
:消耗a.b
(通过调用doSomething
)发生在不同的线程中,或者(如果原始线程只是线程池中的工作线程)从foo
返回后,在调用线程中
不用说,这在OO中是一种相当不自然的风格(Scala可能是最符合人体工程学的语言,这主要是因为标准库未来的实现与actor系统实现非常相似)。(对于“object”,您通常应该将其理解为“对象,在大多数OO语言中实现和使用”)
我认为说“对象只在被要求做某事时才使用线程”并不是那么准确“:更准确的说法是线程使用对象,而不是相反。但无论我们以何种方式看待消费箭头,都必须注意它是不受限制的:一个对象可以在给定的时间点消费/被任意多个线程消费,一个线程可以在给定的时间点消费/被任意多个对象消费
考虑以下Scala代码:
class A(private var b: B) {
def doSomethingWithB(): Unit = {
b.doSomething()
}
}
class B(private var x: Int) {
def doSomething(): Unit = {
x += 1
}
}
def foo(a: A): Unit = {
// yadda yadda yadda
a.doSomethingWithB()
}
线程通过调用doSomethingWithB
进入foo
并使用A
。当仍在使用a
时,它通过调用doSomething
来使用a.b
。它停止消费a.b
,然后停止消费a
对于actor系统,这两个1:N基数最多为1:1
显然,我们可以使对象实现具有类似于参与者的约束:如果使用对象的每个公共方法都需要获得锁,那么一个对象最多只能使用一个线程。同时,对于第二个约束,我们可以通过以下方式进行限制:
// simplified without references to things like ExecutionContexts
class A(...) {
def doSomethingWithB(): Future[Unit] = {
Future.successful(b).flatMap(_.doSomething())
}
}
class B(...) {
def doSomething(): Future[Unit] = {
x += 1
Future.successful(())
}
}
def foo(a: A): Future[Unit] = {
a.doSomethingWithB()
}
现在,当调用doSomethingWithB
时,调用线程(通常)不会消耗a.b
:消耗a.b
(通过调用doSomething
)发生在不同的线程中,或者(如果原始线程只是线程池中的工作线程)从foo
返回后,在调用线程中
不用说,这在OO中是一种相当不自然的风格(Scala可能是最符合人体工程学的语言,主要是因为标准库未来的实现与actor系统实现非常相似)