空闲固定线程池的缺点
Posted
技术标签:
【中文标题】空闲固定线程池的缺点【英文标题】:Drawbacks to an idling fixed threadpool 【发布时间】:2019-12-03 09:43:26 【问题描述】:我目前正在对软件进行各种性能改进。由于它使用 SWT 作为它的 GUI,我遇到了一个问题,在某些情况下,在显示线程中创建了很多 UI 元素。 由于我之前的人并没有真正注意在显示线程之外进行任何计算,因此整个软件在启动时可能会在几秒钟内无响应。 我现在已经隔离了需要在显示线程中执行的代码,我现在正在计算我提交到固定线程池的 Runnables 中的所有其他内容。 我正在使用这样的游泳池:
public abstract class AbstractChartComposite
private static ExecutorService pool = Executors.newFixedThreadPool(8);
private List<String> currentlyProcessingChartItems = new ArrayList<>();
protected void doCalculate(constraints)
for (IMERuntimeConstraint c : constraints)
if(!currentlyProcessingChartItems.contains(c.getId()))
currentlyProcessingChartItems.add(c.getId());
pool.submit(new Runnable()
@Override
public void run()
try
createChartItem(c);
currentlyProcessingChartItems.remove(c.getId());
catch(Throwable e)
e.printStackTrace();
);
我现在想知道,一旦创建了所有 UI 元素,让线程池处于空闲状态是否有任何缺点。我不能真正关闭它以进行垃圾收集,因为当需要创建新元素时,用户输入将再次需要它。 那么让没有提交的 Runnable 运行的线程池有什么主要缺点吗?
【问题讨论】:
并非如此。只是占用一些内存。你也可以有一个非固定的线程池,它也可以缩小到零。 我建议你展示用于创建线程池的代码。 @Thilo 所以你可能会建议像缓存线程池之类的东西?对我来说,这听起来是个好主意。 请注意,您正在从多个线程访问ArrayList
(不是线程安全的),包括修改。总有一天会彻底崩溃的。
@Holger 谢谢,我会在我的代码中解决这个问题
【参考方案1】:
不,没有缺点。
线程实际上不会运行,它们会停放直到提交新任务。所以不影响CPU。您还说您将再次使用此池,因此在您的情况下,没有必要将其关闭并重新创建。
至于内存 - 是的,空闲线程会消耗一些内存,但这也不是问题,直到您拥有数百个(数千个?)线程。
还有一点建议。不要进行过早的优化。这是万恶之源。一旦遇到真正的性能问题,请分析问题,为此使用特殊实用程序并检测瓶颈。
【讨论】:
感谢您的建议。但这并不为时过早。我们的目标是让我们的软件运行一个多星期,以前它总是因为内存问题而崩溃。多年来,它也变得相当迟钝。启动期间 10 秒的冻结是我们再也不能容忍的了。这就是为什么我目前正在研究使用 Visual VM、MAT 进行堆转储分析和其他一些工具进行各种优化。 @Radio,不客气。在这种情况下,调整线程池并不是你真正想做的事情:)专注于系统的其他部分。 好答案。我要提醒您确保在不再需要或应用程序退出时关闭线程池。否则线程可能会在程序结束后继续。 @PavelSmirnov 谢谢。我只是想确保,我在优化时不会引入任何新问题。 附带说明,如果这些空闲线程仍然是一个问题,您可以轻松地将Executors.newFixedThreadPool(8)
替换为new ThreadPoolExecutor(0, 8, 1L, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>())
。然后,一个线程将在空闲至少一分钟时终止,但在需要时重新创建。与newFixedThreadPool
的实现相比,变化很小。但无论如何,答案是对的,8 个空闲线程不会伤害任何人。以上是关于空闲固定线程池的缺点的主要内容,如果未能解决你的问题,请参考以下文章