Akka 参与者与普通对象

Akka 参与者与普通对象,akka,actor,Akka,Actor,来自一本关于使用akka actors的反应式应用程序的书: 由于系统组件仅在收到消息时才对其作出反应,因此系统可以使用可用的 线程来运行当前必须对消息刺激作出反应的应用程序部分。一直以来,, 当前未对消息做出反应的组件没有利用宝贵的CPU资源 但对于不是参与者的正常对象也可以这样说。他们只在被要求做某事时才使用线程。那么,参与者与普通对象有何不同呢?(对于“对象”,您通常应该将其理解为“大多数OO语言中实现和使用的对象”) 我认为说“对象只在被要求做某事时才使用线程”并不准确:更准确的说法是线

来自一本关于使用akka actors的反应式应用程序的书:

由于系统组件仅在收到消息时才对其作出反应,因此系统可以使用可用的 线程来运行当前必须对消息刺激作出反应的应用程序部分。一直以来,, 当前未对消息做出反应的组件没有利用宝贵的CPU资源

但对于不是参与者的正常对象也可以这样说。他们只在被要求做某事时才使用线程。那么,参与者与普通对象有何不同呢?

(对于“对象”,您通常应该将其理解为“大多数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系统实现非常相似)。

(对于“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系统实现非常相似)