javamultithreadingthreadpoolexecutorservicethread-dump

What could be the reason for thread to be parked at java.util.concurrent.ThreadPoolExecutor.getTask


I have an executor which is responsible for consuming messages from a ArrayBlockingQueue.

new ThreadPoolExecutor(1, 1, 0L,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(1),  
                r -> {
                    return new Thread(r, "Request-Queue-Drainer");
                });

Request-Queue-Drainer thread is in WAITING state (Though tasks are being submitted to this thread). The following is the thread-dump.

Name: Request-Queue-Drainer
State: WAITING on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@5b4757a2
Total blocked: 0  Total waited: 8

Stack trace: 
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)

What could be the reason for the thread to be in waiting status?


Solution

  • The thread is waiting because the queue is empty. That's what pool threads do: They pick tasks from the queue and run them, and when the queue is empty, they wait.


    Edit: There's something else that can happen when the queue is empty: The ThreadPoolExecutor can send in a poison pill message that causes a pool thread to die if the number of workers has been greater than the corePoolSize for more than keepAlive time units. That won't happen in your case though because you set the maximumPoolSize and the corePoolSize to the same number (1).


    I don't expect your ThreadPoolExecutor to behave any differently from the one that would be returned by Executors.newFixedThreadPool(1) except that yours can only have one pending task, and it gives the pool thread a special name.