Scala 如何在参与者中停止Source.tick?

Scala 如何在参与者中停止Source.tick?,scala,akka,akka-stream,Scala,Akka,Akka Stream,我有一个演员,每2秒产生一个未使用的。也许它没有任何意义,但它只是为了测试的目的 import akka.NotUsed import akka.actor.{Actor, ActorLogging, Props} import akka.stream.{ActorMaterializer, KillSwitches} import akka.stream.scaladsl.{Keep, Sink, Source} import com.sweetsoft.FsmSystem.{Add, Sta

我有一个演员,每2秒产生一个
未使用的
。也许它没有任何意义,但它只是为了测试的目的

import akka.NotUsed
import akka.actor.{Actor, ActorLogging, Props}
import akka.stream.{ActorMaterializer, KillSwitches}
import akka.stream.scaladsl.{Keep, Sink, Source}
import com.sweetsoft.FsmSystem.{Add, StartTicker, StopTicker}

import scala.concurrent.duration._

object AddActor {

  def props: Props = Props(new AddActor)

}

final class AddActor extends Actor with ActorLogging {

  implicit val materilizer = ActorMaterializer()

  private val consumer: NotUsed => Unit = _ =>
    context.parent ! Add

  private val runnable = Source.tick(2.second, 2.second, NotUsed)
    .named("Ticker")
    .toMat(Sink.foreach(consumer))(Keep.both)

  override def receive: Receive = {
    case StartTicker =>

      runnable.run()
    case StopTicker =>

  }
}  
当参与者收到消息
StopTicker
时,我想停止流。然后通过
StartTicker
,启动流

调用
run()
方法,我将获得具体化的值
cancelabel
,但无法在
StopTicker
范围内访问

我该怎么办

您可以使用以下模式:


将其保存在变量中,但仅使用
val
不可能,对吗?是的,在
Actors
中使用
var
很常见(这不是真正的功能)。只需确保您永远不会在消息处理之外访问它。比如不要关闭它,把它放在
未来
。真的,或者最好用
FSM
建立一个
参与者
?我不知道它之间有什么关系。FSM有状态,所以它本质上是可变的。DSL所做的只是让您将对状态指示符本身的更改隐藏在API后面。我认为这在实践中并不重要。
final class AddActor extends Actor with ActorLogging {
    import context._

    implicit val materilizer: ActorMaterializer = ActorMaterializer()

    private val consumer: NotUsed => Unit = _ =>
      self ! Add //send Add to self rather than directly to context.parent

    private val runnable = Source.tick(2.second, 2.second, NotUsed)
      .named("Ticker")
      .toMat(Sink.foreach(consumer))(Keep.both)

    override def preStart(): Unit = { //start runnable on actor start
      super.preStart()
      runnable.run()
    }

    val running: Receive = { //when running ignore new StartTicker but handle StopTicker and Add
      case StopTicker =>
        become(paused)

      case Add =>
        context.parent ! Add
    }

    val paused: Receive = { //handle just StartTicker
      case StartTicker =>
        become(running)
    }

    override def receive: Receive = paused //initial receive is paused

}