2

I have a thread pool:

ThreadPoolExecutor pool = new ThreadPoolExecutor(cores, 50, 30L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3000));

And then I run:

try {
    pool.execute(() -> 
{
  //Very very long task, fetching from an external URL
});
}catch(Exception e){
    e.printStackTrace();
}

I never get an exception, and this code waits for minutes. What should I do to make it cancel in 30 secs?

avalon
  • 2,231
  • 3
  • 24
  • 49
  • Note: you cannot kill a task this way, all you can do is interrupt the Thread and it is up to the library you are calling to honour this interrupt. You are better off closing the underlying request directly, using the API it provides and letting the task fail. – Peter Lawrey Apr 13 '16 at 07:33

2 Answers2

5

According to the documentation the 3th parameter, keepAlive, does not specify the await time for a specific task in the thread pool, but time till idle threads should be released from the pool.

 * @param keepAliveTime when the number of threads is greater than
 *        the core, this is the maximum time that excess idle threads
 *        will wait for new tasks before terminating.

For your desired behavior you should wrap your task in a FutureTask, then submit the future task to thread pool. On the future task you can call get(timeout, timeunit)

FutureTask<T> task = new FutureTask<T>(c);
pool.execute(task);
return task.get(timeout, timeUnit);
dumitru
  • 2,068
  • 14
  • 23
1

What you're specifying to be 30 seconds is the keepAliveTime of the idle threads of your executor. This is the duration in which excess threads that are not currently processing tasks will be kept alive. Here excess threads is defined as threads created in addition to the one thread per core that your ThreadPoolExecutor will keep alive, depending on the corePoolSize that you've specified.

In order to submit a task with a timeout, you can just submit the task in your ThreadPoolExecutor, take the returned Future and use its timing out get(long timeout, TimeUnit unit) method:

Future<Result> future = pool.execute(yourTask);
Result result = future.get(30, TimeUnit.SECONDS);

You can also take a look at this related question: ExecutorService that interrupts tasks after a timeout

Community
  • 1
  • 1
Dimitar Dimitrov
  • 16,032
  • 5
  • 53
  • 55