我正在努力做一些简单的事情……
我的真实项目多年来一直遭受着一个未知问题的困扰,他们决定创建一个非常简单的测试,结果让我感到恐惧...
这是测试:
ExecutorService t = new ThreadPoolExecutor(10, 20, 60L, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(600));
for (int i = 0; i < 100; i++) {
final int i1 = i;
t.execute(new Runnable() {
@Override
public void run() {
while (true) {
System.out.println(i1);
try {
Thread.sleep(5000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
我正在创建一个包含10个核心线程和20个maximumPoolSize
的线程池
然后我给它100个线程,每个线程将简单地打印一个固定的数字...
我的愚蠢愚蠢的想法是
该池有10个线程,将在某些时间后随机打印0-9 实例将创建10个额外线程,并且池将以0-19打印 随机
这对我来说很明显,因为maxSize为20,在最坏的情况下它应该接受20个任务...
但是结果是永远打印0-9
问题是:如果maximumPoolSize
从未计划执行额外的线程,那又有什么意义呢?
答案 0 :(得分:3)
正如@Oleg指出的那样,该池工作正常,但是有一个我不知道的实现细节。
仅当任务队列已满时才会创建额外的线程
本文更好地解释了: http://www.bigsoft.co.uk/blog/2009/11/27/rules-of-a-threadpoolexecutor-pool-size
以这个例子为例。起始线程池大小为1,核心池大小为 5,最大池大小为10,队列为100。
Sun的方式:随着请求进入线程,最多将创建5个线程,然后 任务将被添加到队列中,直到达到100。 是完整的新线程,最多将创建到maxPoolSize。一旦所有 线程正在使用中,队列已满,将拒绝任务。如 队列减少,活动线程数也减少。
用户预期的方式:随着请求的进入,将创建线程 到10,然后将任务添加到队列,直到队列达到100 他们被拒绝的那一点。线程数将重命名为 最大,直到队列为空。当队列为空时,线程将 消失,直到剩下corePoolSize为止。
因此Java等待最后一秒钟,直到队列耗尽以创建新线程...
答案 1 :(得分:1)
是的,按照@Oleg和您尝试的实现:
新的ThreadPoolExecutor(10、20、60L,TimeUnit.SECONDS,新的ArrayBlockingQueue(600));
在这里, 10是corePoolSize -表示Jvm将为前10个任务的新任务创建新线程。其他任务将被添加到队列中,直到队列已满(600个任务)。
20是maxPoolSize -JVM最多可以创建20个线程。意味着如果已经有10个任务/线程正在运行并且队列中有600个待处理的任务已满,并且如果队列中又有一个新的请求/任务到达,那么JVM将创建最多20个新线程(总线程数=先前的10 +新的10) ;
新的ArrayBlockingQueue(600) =是队列的总大小-它可以在其中排队600个任务。
所有20个线程都运行后,如果新任务到达,则该新任务将被拒绝。
[FROM DOC] SUN内部创建线程的规则:
希望有帮助。