10

I create a ThreadPoolExecutor with this line of code :

private ExecutorService executor = new ThreadPoolExecutor(5, 10, 120, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(20, true));

Then, I run 25 tasks (T01 to T25) so the situation is :

  • 5 tasks currently running (T01 to T05)
  • 20 tasks waiting in the Queue (T06 to T25)

When I put 1 more task (T26), as the queue is full, I expected that the older task (T06) is removed to be launched (because MaxPoolSize is not reached) and the new task (T26) is placed at the end of the queue.

But in real life, if Queue is full and MaxPoolSize is not reached, the newest task is started.

So, I have ...

  • 6 tasks currently running (T01 to T05 and T26)
  • 20 tasks waiting in the Queue (T06 to T25)

... instead of ...

  • 6 tasks currently running (T01 to T06)
  • 20 tasks waiting in the Queue (T07 to T26)

Can I configure the ThreadPoolExecutor to get the expected result ? Should I use another classes ?

For information, part of ThreadPoolExecutor source code

public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
        if (runState == RUNNING && workQueue.offer(command)) {
            if (runState != RUNNING || poolSize == 0)
                ensureQueuedTaskHandled(command);
        }
        else if (!addIfUnderMaximumPoolSize(command))
            reject(command); // is shutdown or saturated
    }
}


private boolean addIfUnderMaximumPoolSize(Runnable firstTask) {
    Thread t = null;
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        if (poolSize < maximumPoolSize && runState == RUNNING)
            t = addThread(firstTask);
    } finally {
        mainLock.unlock();
    }
    if (t == null)
        return false;
    t.start();
    return true;
}

Thanks

1 Answers1

7

I would make the core size equal the maximum. This is how most of the pools are used and I am not sure when would be the downside in your case, but you would get the tasks executed in order.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • I have to agree here. The worst case scenario is you have 5 idle threads, they are suspended anyway so no context switching would occur. – John Vint Dec 13 '10 at 16:57
  • ok but this is a little frustrating -:P ThreadPoolExecutor is exactly what I need except the FIFO order which is not garantee. The idea is to keep 5 threads as much as possible, and temporary overloading the thread executor only when it's needed. If I set maxPoolSize to corePoolSize, I loose the possiblity to temporary overload the thread executor. Anyway, thanks for the response :-) – Jean-Marc Desprez Dec 14 '10 at 16:20
  • I have a question that since the queue is FIFO, if I have 10 task(smaller than min/max core size), can thread pool gareentter that they are executed in order. I mean if I have somthing to do so printRunInfo() in the first line of run(). Is printRunInfo sure to be FIFO? – JaskeyLam Feb 10 '17 at 06:23
  • @Jaskey they are executed in order if you have one thread. If you have multiple threads they will be picked up in order but by the time they are finished, even time started they could be out of order – Peter Lawrey Feb 10 '17 at 09:27
  • @PeterLawrey , I have find out this problem which is very sad, would you please answer my question to clirify why, and sugest a solution : http://stackoverflow.com/questions/42153013/why-tasks-in-threadpool-are-not-executed-following-fifo-java ? Thank you! – JaskeyLam Feb 10 '17 at 09:34