-1

I am trying to schedule a job to run every 10 minutes using ScheduledThreadPoolExecutor. There are 10 threads in the thread pool. Code looks like:

ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(10, r -> {
                    Thread t = new Thread(r);
                    t.setName("thread");
                    return t;
                }, (runnable, pool) -> {
                });

List<ScheduledFuture<?>> listOfFutures = new ArrayList<>();

ScheduledFuture<?> future = executor.scheduleAtFixedRate(() -> {
    try {
        System.out.println("John is a good guy");
    } catch (Exception e) {
        // eat the exception
    }
}, 0, 10, TimeUnit.MINUTES);

listOfFutures.add(future);

Now, if 100 tasks were scheduled and their future were added to a list. When we try to iterate the list and do future.cancel(), out of 100, 2-3 futures turn out to be null.

What is the possible reason here?

I had to add an initial delay of 2 seconds in order to ensure that the future is not null. But I also have an ExecutorService with the same problem (future is null in few cases). But there is no delay that can be added there.

Sart
  • 9
  • 1

1 Answers1

2

Most likely it is that the executor pool has been shutdown or encounted some issue. You've not implemented the RejectedExecutionHandler very clearly, it just discards errors so you have no idea when they occur.

You can get more information on when / how any executor service issue occurs if you drop the last parameter to new ScheduledThreadPoolExecutor to remove the pointless handler (runnable, pool) -> {}. This will instead use the default abort policy.

Alternatively change your rejected handler so that it tells you of the problem when there is one:

(runnable, pool) -> { 
    throw new RejectedExecutionException("*** FAILED ***"
               +" isShutdown()="+pool.isShutdown()
               +" getActiveCount()="+pool.getActiveCount()
               +" queue size="+pool.getQueue().size());
}

When running with your original handler (runnable, pool) -> {} you will need to check each call as you otherwise will have no indication of when there is an issue:

ScheduledFuture<?> future = executor.scheduleAtFixedRate(() -> { ... }, 0, 10, TimeUnit.MINUTES);
if (future == null)
   throw new RuntimeException("*** FAILED to add new action ***");
DuncG
  • 12,137
  • 2
  • 21
  • 33
  • ok, so I have not written the RejectedExecutionHandler. But in my case, it gets executed smoothly if a delay is added. If some issue occurs or the executor has shut down, it should execute the task – Sart Nov 01 '22 at 04:39
  • @Sart Edit the question with details of your cases where `future` is returned as null and there isn't a call to `RejectedExecutionHandler`, or any code that re-produces the issue. – DuncG Nov 01 '22 at 09:49