5

Below is my method in which I have single thread executor to execute some task in the run method.

  private void trigger(final Packet packet) {

    // this line is throwing exception
    Executors.newSingleThreadExecutor().execute(new Runnable() {
      @Override
      public void run() {
        // some code here
      }
    });
  }

Below is the exception I am getting and I am not sure why? What is the best way to fix this?

error= java.util.concurrent.RejectedExecutionException: Task com.abc.stuffProc$2@e033da0 rejected from java.util.concurrent.ThreadPoolExecutor@76c2da8f[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2048)
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:821)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1372)
    at java.util.concurrent.Executors$DelegatedExecutorService.execute(Executors.java:628)

What happens if my trigger method is called many times and it is still working on the run method from my previous threads? Will it launch as many threads or it will wait for one thread to finish and then start another thread?

user1950349
  • 4,738
  • 19
  • 67
  • 119

2 Answers2

1

See here: What could be the cause of RejectedExecutionException

as you could see from the error log, your ThreadPoolExecutor is Terminated.

Maybe this is what you want:

private void trigger(final Packet packet) {

    executor.execute(new Runnable() {
      @Override
      public void run() {
        // some code here
      }
    });
  }

private final ExecutorService executor = Executors.newFixedThreadPool(10);

EDIT Reproduce the Problem with:

public static void main(String[] args) {
    final ExecutorTest et = new ExecutorTest();
    for (int i = 0; i < 50000; i++) {
        et.trigger(i);
    }
    System.out.println("Done");
}

private void trigger(int i) {

    try {
        Executors.newSingleThreadExecutor().execute(() -> {
            try {
                Thread.sleep(1000);
            } catch (final InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        });
    } catch (final Exception e) {
        System.out.println("Test " + i + " with " + Thread.activeCount());
        e.printStackTrace();
    }
}
IEE1394
  • 1,181
  • 13
  • 33
  • What does terminated means? And why it got terminated? – user1950349 Nov 04 '17 at 03:16
  • Try to find out from doc and code when the service is going to be terminated. But currently i have no answer on that. Also tried a small sample event with long running threads and multiple calls. Had no problem with that. Do you have a feelin how many times the trigger i method is called? Are the calls single or multithreaded? – IEE1394 Nov 04 '17 at 03:28
  • I could reproduce your problem with 50000 calls and a delay of a second while executing - so i guess you are in trouble with resources – IEE1394 Nov 04 '17 at 03:38
  • Also the ThreadPoolExecutor overrides finalize() which is a very bad idea to do especially in the way you use it - create many objects which are overriding finalize. https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#finalize() – IEE1394 Nov 04 '17 at 03:46
  • yes you should use fixedThreadPoolSize and create the executor outside – IEE1394 Nov 04 '17 at 09:30
  • @IEE1394 I tried to reproduce using your code with the JDK 1.8.0_112 and got an OOM: `Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread at java.lang.Thread.start0(Native Method)...` Do you get a `RejectedExecutionException`? – Alexandre Dupriez Nov 04 '17 at 10:37
  • yes .. maybe you have not enough HEAP for your application - check your xmx settins. creating 50000 Threads is serious business ;-) – IEE1394 Nov 04 '17 at 10:49
  • @IEE1394 I actually finally reproduced when scaling _down_ the heap to 200 MB (`-Xmx200m`). Interesting - I wonder how much heap is your VM running on to reproduce? – Alexandre Dupriez Nov 04 '17 at 12:28
  • i have also only 256MB Heap for my application. if you have a profiler you could see that the problem is caused by the finalization i guess. Therefore the created objects are referenced while not beeing finalized so they "walking" into the old gen space and removing them is expensive ... so i guess the problem quite similar to out of memory while the jvm is not able to provide the memory for the thread stack - you could tweak it by setting the xss value down – IEE1394 Nov 04 '17 at 12:57
  • @AlexandreDupriez IMO this does not answer the question and neither the linked answer too - there is a third option of why a `RejectedExecutionException` could be thrown - when a thread could not be created and the pool throws it in such a case. – Eugene Nov 05 '19 at 15:19
0

Create ThreadPoolExecutor outside of your trigger method. You should not create newSingleThreadExecutor for every call.

private ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
private void trigger(final Packet packet) {

executorService .execute(new Runnable() {
  @Override
  public void run() {
    // some code here
  }
});

}

Regarding your exception, please check execute method description.

public void execute(Runnable command)

Executes the given task sometime in the future. The task may execute in a new thread or in an existing pooled thread. If the task cannot be submitted for execution, either because this executor has been shutdown or because its capacity has been reached, the task is handled by the current RejectedExecutionHandler.

Since it's unbounded queue, most likely you have called shutdown some where else in your code.

Ravindra babu
  • 37,698
  • 11
  • 250
  • 211