[Akka] Timers, Schedulers

smlee·2023년 10월 12일
0

Akka

목록 보기
31/50
post-thumbnail

일정 시간마다 균일하게 특정 작업을 실행하고 싶은 경우가 있을 것이다. 이런 경우 SchedulerTimer를 사용하여 일정한 기간 동안 반복하여 실행할 수 있다.

Scheduler

스케줄러는 system.scheduler로 접근하여 사용할 수 있다.

(1) scheduleOnce(initialDelay)

scheduleOnce(delayPeriod)deplayPeriod 후에 한 번만 실행하는 것을 뜻한다. 밑의 예시 코드를 한 번 보자.

import scala.concurrent.duration._

val system = ActorSystem("timerSystem)

val simpleActor = system.actorOf(Props[SimpleActor], "simpleActor")

system.scheduler.scheduleOnce(1 second) {
	simpleActor ! InitialMessage
} (system.dispatcher)

위의 코드는 1초 뒤에 SimpleActor에게 InitialMessage를 보내는 코드이다. 이때, delayPeriod를 설정하기 위해 scala.concurrent.duration._을 임포트시켜야 한다. 그리고 중괄호 안에 실행할 동작을 선언한 다음 dispatcher를 넣어주어야 한다.

system.dispatcher는 execution context interface를 구현한 것으로, implicit로 선언하면 굳이 뒤에 쓸 필요가 없다.

import scala.concurrent.duration._

val system = ActorSystem("timerSystem)

val simpleActor = system.actorOf(Props[SimpleActor], "simpleActor")
implicit val executionContext = system.dispatcher

system.scheduler.scheduleOnce(1 second) {
	simpleActor ! InitialMessage
}

즉, 위와 같이 implicit로 암시적으로 선언한다면 자동으로 들어간다.

(2) schedule(initialDelay, period)

schedule 메서드는 initialDelay 이후 매 period마다 블록 내의 행위를 진행시키는 메서드이다.

import scala.concurrent.duration._

val system = ActorSystem("timerSystem)

val simpleActor = system.actorOf(Props[SimpleActor], "simpleActor")

system.scheduler.schedule(1 second, 2 seconds) {
	simpleActor ! InitialMessage
} (system.dispatcher)

위의 코드처럼 schedule은 scheduleOnce처럼 유사하게 코드를 작성하면 된다. 위의 schedule은 1초 후 최초 작업이 시작되며, 2초마다 해당 작업을 반복하는 것을 뜻한다. schedule 역시 period 설정을 위하여 scala.concurrent.duration._을 임포트시키고, system.dispatcher를 인자로 넘겨주어야 한다. 여기서도 implicit를 사용한다면 인자를 굳이 넘기지 않아도 된다.

(3) Cancellable

만약 스케줄링을 취소하고 싶다면 해당 스케줄러를 Cancellable 데이터 타입으로

scheduler를 사용할 때 주의해야 할 점

  1. scheduler 내부에서 unstable한 reference는 사용하지 않는다.
  2. system이 terminate 되었더라도 모든 scheduled task는 집행된다.
  3. 오랜 기간 길게 사용되거나 Milisecond 단위는 정확성이 떨어질 수 있다.

Timer

Timer는 자기자신에게 메시지를 일정 기간 단위로 처리하면서 scheduler보다 간단하고 안전한 도구이다. Timer는 Scheduler와 달리, 액터를 선언할 때 Timer trait를 믹스인하여 구현한다.

import scala.concurrent.duration._

object TimerBasedSCActor {
  case object TimerKey
  case object Start
  case object Reminder
  case object Stop
}

class TimerBasedSCActor extends Actor with ActorLogging with Timers{

  import TimerBasedSCActor._

  timers.startSingleTimer(TimerKey, Start, 500 millis)

  override def receive: Receive = {
    case Start =>
      log.info("Bootstrapping")
      timers.startPeriodicTimer(TimerKey, Reminder, 500 millis)

    case Reminder =>
      log.info("I am alive")

    case Stop =>
      log.warning("Stopping")
      timers.cancel(TimerKey)
      context.stop(self)
  }
}

timers는 많이 쓰이는 메서드들로 startSingleTimer(key, message, period)startPeriodicTimer(key, message, period)가 있다.

timers.startSingleTimer

startSingleTimer(key, message, period)period 후에 타이머 식별자가 key인 타이머를 시작시키며, 자기 자신에게 message를 보내는 타이머이다. 따라서 메시지 핸들러 위에 선언하는 경우가 많다.

timers.startPeriodicTimer

startPeriodicTimer 역시 startSingleTimer와 마찬가지로 key, message, period를 인자로 갖는다. 만약, singleTimer가 존재한다면 이를 종료시키고 periodic timer가 실행된다.

timers.cancel(key)

cancel은 타이머의 식별 key를 가진 타이머를 종료시키는 메서드이다.

0개의 댓글