KosWarm KosWarm - 2 months ago 23
Scala Question

Scala parallel calculation and interrupt when one method returns a result

Given the several methods

def methodA(args:Int):Int={
//too long calculation

def methodB(args:Int):Int={
//too long calculation

def methodC(args:Int):Int={
//too long calculation

They have the same set of arguments and return a result of the same type.

It is necessary to calculate the methods in parallel and when one method returns a result I need to interrupt others.


This was an interesting question. I'm not too experienced, so there is probably a more Scala-ish way to do this, for starters with some of the cancellable future implementations. However, I traded brevity for readability.

import java.util.concurrent.{Callable, FutureTask}

import scala.concurrent.{Await, Future}

import scala.concurrent.duration._

import scala.concurrent.ExecutionContext.Implicits.global

def longRunningTask(foo: Int => String)(arg: Int): FutureTask[String] = {
  new FutureTask[String](new Callable[String]() {
    def call(): String = {
def killTasks(tasks: Seq[FutureTask[_]]): Unit = {
val task1 = longRunningTask(methodA)(3)
val task2 = longRunningTask(methodB)(4)

val task1Future = Future {
val task2Future = Future {
val firstFuture = Future.firstCompletedOf(List(task1Future, task2Future))
  case result => {
    killTasks(List(task1, task2))

So, what I did here? I crated a helper method which creates a FutureTask (from the Java API) which executes an Int => String operation on some Int argument. I also created a helper method which kills all FutureTasks in a collection.

After that I created two long running tasks with two different methods and inputs (that's your part).

The next part is a bit ugly, basically I run the FutureTasks with Future monad and call get to fetch the result.

After that I basically only use the firstCompletedOf method from the Future companion to handle the first finishing task, and when that is processed kill the rest of the tasks.

I'll probably make an effort to make this code a bit better, but start with this.

You should also have a go in checking this with different 'ExecutionContext's, and parallelism levels.