Pooya
Pooya

Reputation: 4481

How to communicate between threads in Scala?

I have a class with some methods in Scala, each method has an execution time, for example methodA takes 10 seconds and methodB takes 5 seconds. and each method calls asynchronously.when I call methodB, it should cancel the thread that is running another methods. I first call methodA, and 2 seconds later I call methodB. What is the best solution for this problem?

def methodA()={
    async{
        // a job that takes 10 seconds
    }
}
def methodB()={
   async{
       // other methods should stop their job
      // a job that takes 5 second
   }
}

def async[T](fn: => Unit): Unit = scala.actors.Actor.actor {
    fn
}

.....

methodA()
methodB()

Upvotes: 0

Views: 694

Answers (1)

0__
0__

Reputation: 67280

Here is an idea, based on the assumption that your method is actively checking whether it should still run or cancel:

import concurrent.{ExecutionContext, Future, Promise, blocking, future, promise}

case class Cancelled() extends RuntimeException

object Job {
  def apply[A](fun: (() => Boolean) => A)(implicit ctx: ExecutionContext): Job[A] = 
    new Job[A] {
      private val p = promise[A]
      def result = p.future
      def cancel(): Unit = p.tryFailure(Cancelled())

      p tryCompleteWith future {
        fun(() => !p.isCompleted)
      }
    }
}
trait Job[A] {
  def result: Future[A]
  def cancel(): Unit
}

So Job embodies a future along with a cancel() method. Your example could be similar to this:

import ExecutionContext.Implicits.global

val a = Job { active =>
  for (i <- 1 to 100 if active()) {
    blocking {
      Thread.sleep(1000)  // doing actual heavy work here
      println(s"A $i")
    }
  }
}

val b = Job { active =>
  for (i <- 1 to 20 if active()) {
    blocking {
      Thread.sleep(1000)  // doing actual heavy work here
      println(s"B $i")
    }
  }
  println("Goodbye A...")
  a.cancel()
}

I have also seen a rather harsh variant that calls Thread.interrupt.

Upvotes: 1

Related Questions