我ThreadPoolExecutor
未能创建新线程。 事实上,我写了一个有点哈克LinkedBlockingQueue
,将接受任何任务(即它是无限的),但调用额外的处理程序-这在我的应用程序喷出警告痕迹,游泳池后面-这给了我非常明确的信息是,TPE被拒绝创建新的线程,即使队列中有成千上万个条目,在它。 我的构造函数如下:
private final ExecutorService s3UploadPool =
new ThreadPoolExecutor(1, 40, 1, TimeUnit.HOURS, unboundedLoggingQueue);
为什么没有创造新主题?
这种疑难杂症是覆盖在这篇博客文章 :
如预期线程池的这种结构根本不起作用。 这是因为在那里新的线程将添加,如果有一个未能提供到队列中的任务的ThreadPoolExecutor中的逻辑。 在我们的例子中,我们使用无界的LinkedBlockingQueue,在这里我们可以随时提供给队列的任务。 这实际上意味着,我们永远不会长出核心池大小,并达到最大池大小。
如果您还需要从脱钩最大池大小最小,你将不得不做一些扩展编码。 我不知道存在于Java库或Apache共享的解决方案的。 该解决方案是创建一个耦合BlockingQueue
是知道TPE,并会走出它的方式拒绝一个任务,如果它知道TPE没有可用线程,然后手动重新排队。 它覆盖在连接后的更多细节。 最终,你的建设将是这样的:
public static ExecutorService newScalingThreadPool(int min, int max, long keepAliveTime) {
ScalingQueue queue = new ScalingQueue();
ThreadPoolExecutor executor =
new ScalingThreadPoolExecutor(min, max, keepAliveTime, TimeUnit.MILLISECONDS, queue);
executor.setRejectedExecutionHandler(new ForceQueuePolicy());
queue.setThreadPoolExecutor(executor);
return executor;
}
然而,更简单的设置corePoolSize
到maxPoolSize
,不要担心这个无稽之谈。
正如@djechlin提到的,这是(到许多令人惊奇的)中限定的的行为的部分ThreadPoolExecutor
。 我相信我已经找到了解决此问题,我表现出在这里我的回答有点优雅的解决方案:
如何获得的ThreadPoolExecutor增加线程最大排队过吗?
基本上你扩展LinkedBlockingQueue
有它总是返回假queue.offer(...)
这将额外的线程,如果有必要添加到池中。 如果池已经是最大线程数和他们都忙, RejectedExecutionHandler
将被调用。 这是处理程序,然后做了put(...)
到队列中。
见我的代码存在。
有一个解决此问题的。 请看下面的实现:
int corePoolSize = 40;
int maximumPoolSize = 40;
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize,
60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
threadPoolExecutor.allowCoreThreadTimeOut(true);
通过设置allowCoreThreadTimeOut()到true
,在池中的线程被允许在指定的超时(60秒在该实施例中)之后终止。 有了这个解决方案,它是corePoolSize
构造函数的参数,确定在实践中,最大池大小,因为线程池将增长到corePoolSize
,然后开始添加作业队列中。 这是可能的池可能永远不会比大,因为池不会产生新的线程,直到队列已满(其中,考虑到LinkedBlockingQueue
有Integer.MAX_VALUE
容量可能永远不会发生)。 因此,人们在制定小点maximumPoolSize
比一个较大的值corePoolSize
。
代价:线程池有0空闲线程后超时已经到期,这意味着会有一些延迟在创建线程之前(通常情况下,你总是有corePoolSize
可用线程)。
更多的细节可以在JavaDoc中可以找到的ThreadPoolExecutor 。