【问题标题】: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 谢谢,我会在我的代码中解决这个问题

标签: java multithreading performance threadpool


【解决方案1】:

不,没有缺点。

线程实际上不会运行,它们会停放直到提交新任务。所以不影响CPU。您还说您将再次使用此池,因此在您的情况下,没有必要将其关闭并重新创建。

至于内存 - 是的,空闲线程会消耗一些内存,但这也不是问题,直到您拥有数百个(数千个?)线程。

还有一点建议。不要进行过早的优化。这是万恶之源。一旦遇到真正的性能问题,请分析问题,为此使用特殊实用程序并检测瓶颈。

【讨论】:

  • 感谢您的建议。但这并不为时过早。我们的目标是让我们的软件运行一个多星期,以前它总是因为内存问题而崩溃。多年来,它也变得相当迟钝。启动期间 10 秒的冻结是我们再也不能容忍的了。这就是为什么我目前正在研究使用 Visual VM、MAT 进行堆转储分析和其他一些工具进行各种优化。
  • @Radio,不客气。在这种情况下,调整线程池并不是你真正想做的事情:)专注于系统的其他部分。
  • 好答案。我要提醒您确保在不再需要或应用程序退出时关闭线程池。否则线程可能会在程序结束后继续。
  • @PavelSmirnov 谢谢。我只是想确保,我在优化时不会引入任何新问题。
  • 附带说明,如果这些空闲线程仍然是一个问题,您可以轻松地将Executors.newFixedThreadPool(8) 替换为new ThreadPoolExecutor(0, 8, 1L, TimeUnit.MINUTES, new LinkedBlockingQueue&lt;Runnable&gt;())。然后,一个线程将在空闲至少一分钟时终止,但在需要时重新创建。与newFixedThreadPool 的实现相比,变化很小。但无论如何,答案是对的,8 个空闲线程不会伤害任何人。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-13
  • 1970-01-01
  • 1970-01-01
  • 2019-08-18
  • 2015-02-28
  • 2011-08-19
  • 2017-12-07
相关资源
最近更新 更多