线程池没有调整大小

Kaa*_*rde 5 java multithreading threadpool threadpoolexecutor

我想创建一个缓存的线程池,但它作为一个固定的线程池.目前我有这个代码:

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 "";
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我运行代码,我得到输出:

pool-1-thread-1 is ready
pool-1-thread-2 is ready
pool-1-thread-1 is ready
pool-1-thread-2 is ready
...
Run Code Online (Sandbox Code Playgroud)

意味着只有2个线程正在完成所有工作,并且没有新的工作线程添加到池中.如果任务在队列中等待(在我的情况下最多10个),线程池不应该产生更多线程吗?

我不想使用,Executors.newCachedThreadPool()因为它实际上没有最大线程的上限,它有corePoolSize0.我希望一直准备好一些线程以获得更好的响应能力.

-----编辑1 -----

谢谢Aleksey的答案.设置队列容量使其行为符合预期,但现在我遇到了一个新问题.

后台任务的数量差异很大.大部分时间为0但短期内最多可同时执行50个并发任务.处理这个问题的有效方法是什么?请记住,大多数后台任务都是短暂的(<1s),但也有一些长期任务(> 1分钟).

如果我像这样设置我的线程池:

ExecutorService threadPool = new ThreadPoolExecutor(2, 10, 180, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10));
Run Code Online (Sandbox Code Playgroud)

我很可能会因峰值使用而得到RejectedExecutionException.但是如果我像这样设置threadpool:

ExecutorService threadPool = new ThreadPoolExecutor(2, 10, 180, TimeUnit.SECONDS, new LinkedBlockingQueue<>(200));
Run Code Online (Sandbox Code Playgroud)

然后,不会添加新的工作线程,因为队列不会最大化.

CPU至少有4个核心,所以这在我看来会很浪费.并且大多数时候根本没有任何后台任务(80%的正常运行时间),因此在我看来,保留固定的线程池也是浪费.

Ale*_*lev 4

ThreadPoolExecutorJavadoc 说:

当在方法execute(Runnable)中提交新任务并且正在运行的线程少于corePoolSize时,即使其他工作线程处于空闲状态,也会创建一个新线程来处理该请求。如果运行的线程数大于 corePoolSize 但小于 maxPoolSize,则仅当队列已满时才会创建新线程

YourLinkedBlockingQueue永远不会满,因为它没有元素数量的上限。更改new LinkedBlockingQueue()为new LinkedBlockingQueue(10)可以解决这个问题。