psisoyev
psisoyev

Reputation: 2168

Scala looping for certain duration

I'm looking for a possibility to loop for certain duration. For example, I'd like to println("Hi there!") for 5 minutes.

I'm using Scala and Akka.

I was thinking about using future, which will be finished in 5 minutes, meanwhile I would use while cycle on it with check that it's not completed. Such approach doesn't work for me, as my class isn't an actor, and I cant finish the future from outside the loop.

Any ideas or maybe there are ready solutions for such things?

Current ugly solution:

    def now = Calendar.getInstance.getTime.getTime
    val ms = durationInMins * 60 * 1000
    val finish = now + ms

    while (now <= finish) {
       println("hi")
    }

Thanks in advance!

Upvotes: 7

Views: 3626

Answers (3)

abatyuk
abatyuk

Reputation: 1342

You can also do it in the actor manner:

case object Init
case object Loop
case object Stop

class Looper extends Actor {
    var needToRun = true

    def receive = {
        case Init =>
            needToRun = true
            self ! Loop
        case Stop =>
            needToRun = false
        case Loop =>
            if(needToRun) {
                //do whatever you need to do
                self ! Loop
            }
    }
}

And use scheduler to send a message:

looperRef ! Init
system.scheduler.scheduleOnce(5 MINUTES, looperRef, Stop)

Upvotes: 0

tabdulradi
tabdulradi

Reputation: 7596

val timeout = future{Thread.sleep(5000)}
while(!timeout.isCompleted){println("Hello")}

This works, but I don't like it because:

  1. Long loops without sleeps are bad.
  2. Long loops in the main Thread is blocking your application

Another solution, would be to move your logic (the print function) into a separate Actor, and introduce a scheduler to handle the timing for you, and another scheduler-once to send a PoisonPill after a duration

More about Scheduler

Upvotes: 0

drexin
drexin

Reputation: 24423

The solution of @Radian is potentially dangerous, as it will eventually block all the threads in the ExecutorService, when your app runs this code several times concurrently. You can better use a Deadline for that:

import scala.concurrent.duration._

val deadline = 5.seconds.fromNow

while(deadline.hasTimeLeft) {
  // ...
}

Upvotes: 23

Related Questions