- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我想创建一个缓存线程池,但它充当固定线程池。目前我有这段代码:
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 "";
}
}
如果我运行代码,我会得到输出:
pool-1-thread-1 is ready
pool-1-thread-2 is ready
pool-1-thread-1 is ready
pool-1-thread-2 is ready
...
意味着只有 2 个线程在做所有的工作,并且没有新的工作线程被添加到池中。如果任务在队列中等待(在我的例子中最多 10 个),线程池不应该生成更多线程吗?
我不想使用 Executors.newCachedThreadPool()
因为它对最大线程几乎没有上限并且它有 corePoolSize
0。我想要一些线程随时准备就绪以获得更好的响应能力。
----- 编辑 1 -----
谢谢阿列克谢的回答。将容量设置为队列使其按预期运行,但现在我遇到了一个新问题。
后台任务的数量变化很大。大部分时间为 0,但短时间内最多可以执行 50 个并发任务。处理这个问题的有效方法是什么?请记住,大多数后台任务都是短期的 (< 1s),但也有一些长期任务 (> 1 分钟)。
如果我这样设置我的线程池:
ExecutorService threadPool = new ThreadPoolExecutor(2, 10, 180, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10));
我很可能会在使用高峰时遇到 RejectedExecutionException。但是,如果我像这样设置线程池:
ExecutorService threadPool = new ThreadPoolExecutor(2, 10, 180, TimeUnit.SECONDS, new LinkedBlockingQueue<>(200));
然后不会添加新的工作线程,因为队列不会达到最大值。
CPU 至少有 4 个内核,所以我认为这很浪费。大多数时候根本没有任何后台任务(80% 的正常运行时间),所以在我看来保持固定的线程池也是一种浪费。
最佳答案
ThreadPoolExecutor
Javadoc 说:
When a new task is submitted in method execute(Runnable), and fewer than corePoolSize threads are running, a new thread is created to handle the request, even if other worker threads are idle. If there are more than corePoolSize but less than maximumPoolSize threads running, a new thread will be created only if the queue is full
您的 LinkedBlockingQueue
永远不会满,因为它没有元素数量的上限。将 new LinkedBlockingQueue()
更改为 new LinkedBlockingQueue(10)
即可解决该问题。
关于java - 线程池不调整大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33752726/
我是一名优秀的程序员,十分优秀!