Thread pool does not change

I want to create a pool of cached streams, but it acts as fixed. I currently have this code:

public class BackgroundProcesses { public static void main(String[] args) throws InterruptedException, ExecutionException { //ExecutorService threadPool2 = Executors.newCachedThreadPool(); ExecutorService threadPool = new ThreadPoolExecutor(2, 10, 180, TimeUnit.SECONDS, new LinkedBlockingQueue<>()); for (int i = 0; i < 800; i++) { Callable<String> task = new Task(); threadPool.submit(task); } } } class Task implements Callable<String> { @Override public String call() throws Exception { Thread.sleep(100); System.out.println(Thread.currentThread().getName() + " is ready"); return ""; } } 

If I run the code, I get the output:

 pool-1-thread-1 is ready pool-1-thread-2 is ready pool-1-thread-1 is ready pool-1-thread-2 is ready ... 

A value of just 2 threads does all the work, and new worker threads are not added to the pool. Doesn't threadpool create more threads if tasks are waiting in line (up to 10 in my case)?

I do not want to use Executors.newCachedThreadPool() because it has virtually no upper limit for maximum threads, and it has corePoolSize 0. I want some threads to be ready for all times for better responsiveness.

----- edit 1 -----

Thanks to Alexey for the answer. Putting a container in a queue causes it to behave as expected, but now I have a new problem.

The number of background jobs varies greatly. Most of the time, 0, but can perform up to 50 simultaneous tasks for short periods. What would be an effective way to handle this? Keep in mind that most background tasks will be short-lived (<1s), but several long-lived tasks (> 1 minute).

If I installed my thread, do the following:

 ExecutorService threadPool = new ThreadPoolExecutor(2, 10, 180, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10)); 

I most likely get a RejectedExecutionException with maximum use. However, if I installed threadpool like this:

 ExecutorService threadPool = new ThreadPoolExecutor(2, 10, 180, TimeUnit.SECONDS, new LinkedBlockingQueue<>(200)); 

Then new workflows will not be added, because the queue will not be maximum.

The processor has at least 4 cores, therefore, in my opinion, this would be wasteful. And most of the time there are no background tasks at all (80% of the time), so keeping a fixed pool of threads will also be wasteful, in my opinion.

+5
source share
1 answer

ThreadPoolExecutor Javadok says:

When a new task is dispatched when the (Runnable) method is executed and smaller than the corePoolSize threads are running, a new thread is created to process the request, even if other workflows are inactive. If there is more than corePoolSize, but less than maximum threads, PoolSize, a new thread will be launched only if the queue is full

Your LinkedBlockingQueue never populated because it does not have an upper bound on the number of elements. Changing new LinkedBlockingQueue() to new LinkedBlockingQueue(10) will solve this.

+4
source

Source: https://habr.com/ru/post/1236124/


All Articles