0

If I do Thread.sleep, I get RejectedExecutionException, otherwise, the code works fine.

Is it not possible to make the thread sleep for some time?

import java.util.concurrent.{Executors, TimeUnit}
import scala.concurrent.{ExecutionContext, Future, blocking}
import scala.util.{Failure, Success}

val executorService = Executors.newFixedThreadPool(2)
implicit val exec = ExecutionContext.fromExecutorService(executorService)

Future { blocking{
    println("Thread sleeps...")
    Thread.sleep(100)  // <<<< causes exception on 'shutdown'
    println("Thread running again...")
}} onComplete {
  case Success(_) => println("Done ABC")
  case Failure(exception) => println(exception)
}
exec.shutdown()
exec.awaitTermination(1000, TimeUnit.MILLISECONDS)

outputs:

Thread sleeps...
Thread running again...
java.util.concurrent.RejectedExecutionException: Task scala.concurrent.impl.CallbackRunnable@79834f9b rejected from java.util.concurrent.ThreadPoolExecutor@35267234[Shutting down, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 0]
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
    at scala.concurrent.impl.ExecutionContextImpl$$anon$1.execute(ExecutionContextImpl.scala:136)
    at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:44)
    at scala.concurrent.impl.Promise$DefaultPromise.tryComplete(Promise.scala:252)
    at scala.concurrent.Promise$class.complete(Promise.scala:55)
    at scala.concurrent.impl.Promise$DefaultPromise.complete(Promise.scala:157)
    at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:23)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Saurav Sahu
  • 13,038
  • 6
  • 64
  • 79
  • `fixedThreadPool` uses a fixed number of threads (thus "fixed"). If all both of them are sleeping, then subsequent executions are rejected, because there are no threads left to serve them. – Dima Apr 09 '21 at 16:22
  • Even if I increased the number of threads in the pool to 8, the result was the same. Removing the `onComplete` block immediately fixed the problem, or alternatively, I can comment out the shutdown of ExecutorService. – Saurav Sahu Apr 09 '21 at 16:26
  • Yes, in this case, the exception was because you were trying to start an execution after executor is shut down. Regardless, blocking a pooled thread is never a good idea, especially, with a limited number of threads available. – Dima Apr 09 '21 at 16:28
  • 1
    Your `exec.shutdown()` is issued too soon. See this [SO link](https://stackoverflow.com/questions/8183205/what-could-be-the-cause-of-rejectedexecutionexception/8183463) for possible causes of `RejectedExecutionException`. – Leo C Apr 09 '21 at 16:31

2 Answers2

1

By removing onComplete, I see there is no exception. I had registered a callback by using the onComplete, but the operation ExecutorService.shutdown must not be allowing any new tasks to be accepted.

If the future has completed, the function should be applied immediately or scheduled asynchronously. This didn't work because of the shutdown of executor service in my case.

Saurav Sahu
  • 13,038
  • 6
  • 64
  • 79
1

If I do Thread.sleep, I get RejectedExecutionException, otherwise, the code works fine.

This problem is completely unrelated to Thread.sleep—since a Future only schedules its callbacks once its result is available, your code has a race-condition between starting the computations associated with the Future, and shutting down the ExecutionContext.

Is it not possible to make the thread sleep for some time?

This is a completely different question to the one above—if you want to use a Timer-facility, you can use that and complete the Future once your Timer triggers (after a delay).

For a discussion around timers, see: How to implement a delayed future without java.util.Timer?

Viktor Klang
  • 26,479
  • 7
  • 51
  • 68