优化线程池执行器-java



我正在使用ThreadPoolexecutor,将其替换为遗留的Thread。

我创建了如下执行器:

pool = new ThreadPoolExecutor(coreSize, size, 0L, TimeUnit.MILLISECONDS,
       new LinkedBlockingQueue<Runnable>(coreSize),
       new CustomThreadFactory(name),
       new CustomRejectionExecutionHandler());
pool.prestartAllCoreThreads();

这里的核心大小是最大池大小/5。 我已经在应用程序启动时预先启动了大约 160 个线程的所有核心线程。

在传统设计中,我们创建并启动了大约 670 个线程。

但关键是,即使在使用Executor并创建和替换旧设计之后,我们也没有获得更好的结果。

对于结果内存管理,我们使用 top 命令来查看内存使用情况。为了时间,我们已经将System.currentTime的记录器放置在millis中以检查使用情况。

请告诉如何优化此设计。 谢谢。

但关键是,即使在使用Executor并创建和替换旧设计之后,我们也没有获得更好的结果。

我假设您正在查看应用程序的整体吞吐量,并且与在自己的线程中运行每个任务(即不使用池(相比,您没有看到更好的性能?

这听起来像您没有因为上下文切换而被阻止。 也许您的应用程序受 IO 限制或以其他方式等待其他系统资源。 670 个线程听起来很多,你会使用大量的线程堆栈内存,但除此之外,它可能不会阻碍你的应用程序的性能。

通常,我们使用ExecutorService类不一定是因为它们比原始线程,而是因为代码更易于管理。 并发类可以处理很多锁定、排队等问题。

几个代码注释:

  • 我不确定您是否希望LinkedBlockingQueue受到核心大小的限制。 这是两个不同的数字。 核心大小是池中的最小线程数。 BlockingQueue的大小是有多少作业可以排队等待空闲线程。

  • 顺便说一句,ThreadPoolExecutor永远不会分配超过核心线程数的线程,除非BlockingQueue已满。 在您的情况下,如果所有核心线程都繁忙并且队列已满,核心大小的排队任务数是下一个线程分叉时。

  • 我从来没有使用过pool.prestartAllCoreThreads();. 一旦任务提交到池中,核心线程就会启动,所以我认为它不会给你带来太多好处——至少对于长时间运行的应用程序来说不会。

为了时间,我们已经将System.currentTime的记录器放置在millis中以检查使用情况。

对此要小心。 过多的记录器对应用程序性能的影响可能大于重新构建应用程序。 但我假设您在没有看到性能改进添加了记录器。

执行器只是包装线程的创建/使用,所以它没有做任何神奇的事情。

听起来你在其他地方遇到了瓶颈。您是否锁定了单个对象?您是否有一个每个线程都命中的单线程资源?在这种情况下,您不会看到行为的任何变化。

您的进程是否受 CPU 限制?如果是这样,您的线程应该(粗略地说(与可用的处理内核数量相匹配。请注意,您创建的每个线程都会消耗其堆栈的内存,如果您受内存限制,则创建多个线程在这里无济于事。

相关内容

  • 没有找到相关文章

最新更新