0

Is there any way to interrupt a parallel collection computation in Scala?

Example:

val r = new Runnable {
  override def run(): Unit = {
    (1 to 3).par.foreach { _ => Thread.sleep(5000000) }
  }
}
val t = new Thread(r)
t.start()
Thread.sleep(300) // let them spin up
t.interrupt()

I'd expect t.interrupt to interrupt all threads spawned by par, but this is not happening, it keeps spinning inside ForkJoinTask.externalAwaitDone. Looks like that method clears the interrupted status and keeps waiting for the spawned threads to finish.

This is Scala 2.12

eprst
  • 733
  • 6
  • 14

1 Answers1

2

The thread that you t.start() is responsible just for starting parallel computations and to wait and gather the result.

It is not connected to threads that compute operations. Usually, it runs on default forkJoinPool that independent from the thread that submits computation tasks.

If you want to interrupt the computation, you can use custom execution back-end (like manually created forkJoinPool or a threadPool), and then shut it down. You can read about that here.

Or you can provide a callback from the computation.

But all those approaches are not so good for such a case.

If you producing a production solution or your case is complex and critical for the app, you probably should use something that has cancellation by design. Like Monix.Task or CancellableFuture.

Or at least use Future and cancel it with workarounds.

Artem Sokolov
  • 810
  • 4
  • 8
  • I know how to work this around, there are many ways. But that's a lot of boilerplate to implement the behavior that should be there from the start IMO. I don't see any logic behind `t.interrupt()` being a no-op. I'd be using `ForkJoinTask.get()`, not `.join()` in `WrappedTask.sync` and handle interruptions correctly. – eprst Aug 06 '20 at 23:48