为什么线程池只创建一个线程?
Why threadpool creates only one thread?
我写了代码示例:
class Test {
public static void main(String[] args) throws InterruptedException {
ThreadPoolExecutor executorService = new ThreadPoolExecutor(0, 100,
2L, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>());
executorService.allowCoreThreadTimeOut(true);
CountDownLatch countDownLatch = new CountDownLatch(20);
long l = System.currentTimeMillis();
for (int i = 0; i < 20; i++) {
Thread.sleep(100);
executorService.submit(new Runnable() {
@Override
public void run() {
try {
countDownLatch.countDown();
Thread.sleep(500);
} catch (Exception e) {
System.out.println(e);
}
}
});
}
executorService.shutdown();
countDownLatch.await();
System.out.println((System.currentTimeMillis() - l) / 100);
}
}
每100毫秒提交新任务(总任务数量- 20)。每个任务持续时间 - 0.5 秒。因此可以并行执行 5 个任务,最佳执行时间为:20*100+500 = 2.5 秒,池应创建 5 个线程
但我的实验显示 9.6 秒。
我打开 jsvisualvm
查看创建了多少个线程池,我看到只创建了一个线程:
请更正我的 threadPool 配置不正确的地方。
我猜测此行为的答案可能源于:
ThreadPoolExecutor 将根据 corePoolSize(参见 getCorePoolSize())和 maximumPoolSize(参见 getMaximumPoolSize())设置的边界自动调整池大小(参见 getPoolSize())。当在方法 execute(java.lang.Runnable) 中提交了一个新任务,并且少于 corePoolSize 线程 运行 时,将创建一个新线程来处理请求,即使其他工作线程处于空闲状态。如果线程数大于corePoolSize小于maximumPoolSize运行,只有队列满了才会创建新线程
(来自 ThreadPoolExecutor javadoc)。
问题是:休眠 线程如何进入这个等式。我的建议:将 corePoolSize 从 0 更改为 10;并将最大池大小也设置为 10。
原因可以从ThreadPoolExecutor javadoc中找到。
Any BlockingQueue may be used to transfer and hold submitted tasks.
The use of this queue interacts with pool sizing: If fewer than
corePoolSize threads are running, the Executor always prefers adding a
new thread rather than queuing.
If corePoolSize or more threads are
running, the Executor always prefers queuing a request rather than
adding a new thread.
If a request cannot be queued, a new thread is
created unless this would exceed maximumPoolSize, in which case, the
task will be rejected.
因此,由于您的 corePoolSize
为 0,因此未使用第一个选项,并且由于您的队列是无限的,因此未使用最后一个选项。所以剩下的排队策略就是你得到的。
修改corePoolSize
或者workQueue
的大小可以看到不同的结果。
我写了代码示例:
class Test {
public static void main(String[] args) throws InterruptedException {
ThreadPoolExecutor executorService = new ThreadPoolExecutor(0, 100,
2L, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>());
executorService.allowCoreThreadTimeOut(true);
CountDownLatch countDownLatch = new CountDownLatch(20);
long l = System.currentTimeMillis();
for (int i = 0; i < 20; i++) {
Thread.sleep(100);
executorService.submit(new Runnable() {
@Override
public void run() {
try {
countDownLatch.countDown();
Thread.sleep(500);
} catch (Exception e) {
System.out.println(e);
}
}
});
}
executorService.shutdown();
countDownLatch.await();
System.out.println((System.currentTimeMillis() - l) / 100);
}
}
每100毫秒提交新任务(总任务数量- 20)。每个任务持续时间 - 0.5 秒。因此可以并行执行 5 个任务,最佳执行时间为:20*100+500 = 2.5 秒,池应创建 5 个线程
但我的实验显示 9.6 秒。
我打开 jsvisualvm
查看创建了多少个线程池,我看到只创建了一个线程:
请更正我的 threadPool 配置不正确的地方。
我猜测此行为的答案可能源于:
ThreadPoolExecutor 将根据 corePoolSize(参见 getCorePoolSize())和 maximumPoolSize(参见 getMaximumPoolSize())设置的边界自动调整池大小(参见 getPoolSize())。当在方法 execute(java.lang.Runnable) 中提交了一个新任务,并且少于 corePoolSize 线程 运行 时,将创建一个新线程来处理请求,即使其他工作线程处于空闲状态。如果线程数大于corePoolSize小于maximumPoolSize运行,只有队列满了才会创建新线程
(来自 ThreadPoolExecutor javadoc)。
问题是:休眠 线程如何进入这个等式。我的建议:将 corePoolSize 从 0 更改为 10;并将最大池大小也设置为 10。
原因可以从ThreadPoolExecutor javadoc中找到。
Any BlockingQueue may be used to transfer and hold submitted tasks.
The use of this queue interacts with pool sizing: If fewer than corePoolSize threads are running, the Executor always prefers adding a new thread rather than queuing.
If corePoolSize or more threads are running, the Executor always prefers queuing a request rather than adding a new thread.
If a request cannot be queued, a new thread is created unless this would exceed maximumPoolSize, in which case, the task will be rejected.
因此,由于您的 corePoolSize
为 0,因此未使用第一个选项,并且由于您的队列是无限的,因此未使用最后一个选项。所以剩下的排队策略就是你得到的。
修改corePoolSize
或者workQueue
的大小可以看到不同的结果。