everyone.
I have a misunderstanding of working with Thread Pools. The real result differs from API description of this class. When I am using LinkedBlockedQueue in Thread pool with it does not reuse threads, thread pool wait KeepAliveTime that was set in the constructor, then kill this thread and create a new one. When I set KeepAliveTime small, like 1 second or less it deletes thread a recreate it, but if I set for a minute new threads aren't created because MaxPoolSize doesn't allow it and queue already full so all tasks rejected, but threads for which keepAliveTime set minute doing nothing this time. I am quite new and don't understand why it doesn't reuse these threads. after keepTimeAlive expiration it kills these thread and if queue full, it creates a new one. Why it works this way? As far as I understood from API it has to reuse it if threads are idle during keepAliveTime. It reuses threads when I used SynchronousQueue, but not LinkedBlockingQueue.
public class Main {
private volatile int remainingTasksCount;
private volatile static ThreadPoolExecutor consumer = new ThreadPoolExecutor(1, 2, 1, TimeUnit.MINUTES, new LinkedBlockingQueue<>(3));
private static Runnable task = () -> {
System.out.println(String.format("consumer %s, id %s, size %s, active count %s, queue %s",
Thread.currentThread().getName(), Thread.currentThread().getId(),
consumer.getPoolSize(), consumer.getActiveCount(), 3-consumer.getQueue().remainingCapacity()));
String s = new String();
synchronized (s) {
try {
s.wait(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
public static void main(String[] args) throws IOException {
try {
new Thread(() -> {
while (true) {
try {
for (int i = 0; i < 5; i++) {
consumer.submit(task);
}
System.out.println("PUSH TASKS");
synchronized (Thread.currentThread()) {
Thread.currentThread().wait(10000);
}
} catch (Throwable th) {
System.out.println(th);
}
}
}).start();
} catch (Throwable th) {
System.out.println(th);
}
}
OUTPUT
PUSH TASKS
consumer pool-1-thread-1, id 15, size 2, active count 2, queue 3
consumer pool-1-thread-2, id 16, size 2, active count 2, queue 3
consumer pool-1-thread-2, id 16, size 2, active count 2, queue 1
consumer pool-1-thread-1, id 15, size 2, active count 1, queue 2
consumer pool-1-thread-1, id 15, size 2, active count 1, queue 0
Disconnected from the target VM, address: '127.0.0.1:64434', transport: 'socket'
Process finished with exit code 1
But next time producer submit tasks, I get RejectedExecutionException
if I change keepAliveTime to 1 Second. Everything is working well, but creates
new Threads.
PUSH TASKS
consumer pool-1-thread-2, id 16, size 2, active count 2, queue 3
consumer pool-1-thread-1, id 15, size 2, active count 2, queue 3
consumer pool-1-thread-2, id 16, size 2, active count 2, queue 2
consumer pool-1-thread-1, id 15, size 2, active count 2, queue 1
consumer pool-1-thread-2, id 16, size 2, active count 1, queue 0
PUSH TASKS
consumer pool-1-thread-3, id 17, size 2, active count 2, queue 3
consumer pool-1-thread-2, id 16, size 2, active count 2, queue 2
consumer pool-1-thread-3, id 17, size 2, active count 2, queue 1
consumer pool-1-thread-2, id 16, size 2, active count 2, queue 1
consumer pool-1-thread-3, id 17, size 2, active count 1, queue 0
consumer pool-1-thread-3, id 17, size 1, active count 1, queue 2
PUSH TASKS
consumer pool-1-thread-4, id 18, size 2, active count 2, queue 3
consumer pool-1-thread-3, id 17, size 2, active count 2, queue 1
consumer pool-1-thread-4, id 18, size 2, active count 2, queue 1
consumer pool-1-thread-3, id 17, size 2, active count 1, queue 0
PUSH TASKS
consumer pool-1-thread-3, id 17, size 2, active count 2, queue 2
consumer pool-1-thread-5, id 19, size 2, active count 2, queue 3
consumer pool-1-thread-3, id 17, size 2, active count 2, queue 1
consumer pool-1-thread-5, id 19, size 2, active count 2, queue 1
consumer pool-1-thread-3, id 17, size 2, active count 1, queue 0
I will be glad if someone could explain me my fault, or something basic principle that I missed
Executors.newCachedThreadPool()?ExecutorService. If you are trying to limit the active threads then useExecutors.newFixedThreadPool(15). That will only allow 15 executing threads at once but will allow you to queue up as many jobs as you like.