0

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()

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Good solution, but in my project, threads or jobs can not find each other to cancel. in your solution b knows that there is an a job
Ah well, then you just need to a keep a global list of running jobs. It should be straight forward to register them within the Job.apply method.
Ok, but what is the identifier of job inside the apply method to register it in a global map?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.