Home > Software engineering >  How to kill all threads caused by Scala .par when one throws and exception?
How to kill all threads caused by Scala .par when one throws and exception?

Time:10-12

This code blocks, the exceptions that are thrown don't kill the loop

List(1, 2, 3, 4, 5).par.foreach { i =>
        println("i = "   i)

        if (i == 5) {
          println("Sleeping forever")
          java.lang.Thread.sleep(Long.MaxValue)
        }

        throw new IllegalArgumentException("foo")
      } must throwA[IllegalArgumentException]

Is there a way to use .par but make it blow up properly?

CodePudding user response:

I think that when using the par libs you should expect the exception to occour once all the threads actually finish and are are joined back into the current thread, I suspect this because by looking at the implementation of the foreach method (cmd clicking on foreach) a method named executeAndWaitResult is used

Here are some other q/s that seem somewhat similar perhaps it helps interrupt scala parallel collection How to cancel Future in Scala?

https://immutables.pl/2016/10/08/parallel-futures-and-exceptions/

CodePudding user response:

This seems to work, but verbose though

implicit class PimpedListScala[T](l: List[T]) {
    def parForeachThrowOnException(f: T => Unit): Unit = {
      var exception: Option[Throwable] = None

      val future = Future(
        l.par.foreach(e =>
          try {
            f(e)
          } catch {
            case t: Throwable =>
              if (exception.isEmpty) exception = Some(t)
          }
        )
      )

      while (exception.isEmpty && !future.isCompleted) {
        java.lang.Thread.sleep(5000)
      }

      exception.foreach(throw _)
    }
  }
  • Related