当前位置: 首页 > 知识库问答 >
问题:

线程池执行器-java 的优化

翟柏
2023-03-14

我使用线程池执行器,将其替换为旧版线程。

我创建了如下执行器:

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

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

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

但关键是,即使在使用Executor并创建和替换遗留设计之后,我们也不会得到更好的结果。

对于结果内存管理,我们使用Top命令来查看内存使用情况。对于时间,我们将System.current时间的记录器以毫秒为单位来检查使用情况。

请说明如何优化此设计。谢谢

共有2个答案

仇飞鹏
2023-03-14

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

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

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

唐弘益
2023-03-14

但关键是,即使在使用Executor并创建和替换遗留设计之后,我们也不会得到更好的结果。

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

这听起来就像你没有因为上下文切换而被阻塞。也许你的应用程序是IO绑定的,或者在等待其他系统资源。670线程听起来很多,你会使用很多线程堆栈内存,但除此之外,它可能不会阻碍你的应用程序的性能。

通常我们使用< code>ExecutorService类不一定是因为它们比原始线程快,而是因为代码更容易管理。并发类负责大量的锁定、排队等工作。脱离你的控制。

几个代码注释:

>

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

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

    我从来没有用过< code > pool . prestartallcorethreads();。一旦任务被提交到池中,核心线程就会被启动,所以我不认为这对你有什么好处——至少对一个长时间运行的应用程序来说是这样。

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

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

  •  类似资料:
    • 我正在使用线程池执行器更改遗留设计。详情如下:- 遗留:-对于遗留设计,在应用程序启动时创建600个线程。和放置在各种池中,然后在需要时提取这些池,并将任务分配给相应的线程。 新:-在新设计中,我将线程池替换为执行器服务 我观察到的是,对于Executor,在启动时不会创建线程。它们是在从客户端激发请求时创建的。因此,与前一个线程相比,在内存中创建的线程要少得多。 但我的问题是,这样做是否正确,因

    • Java SE6文档中的ThreadPoolExecutor类具有以下方法: 返回正在积极执行任务的线程的大致数目。 这里近似和积极执行是什么意思? 在调用之前、期间和之后,是否保证 null 我已经研究了线程池执行器监视需求,以及如何在java中判断线程池中是否有可用的线程,但它们没有回答我的查询。

    • 我正在编写一个定制的ThreadPoolExecutor,具有以下额外功能:- > 如果有理想的线程,并且随着任务的到来,将该任务分配到队列中,而不是将其添加到队列中。 如果所有线程(最大池大小)都忙,则在新任务到来时,使用RejectionHandler的reject方法将它们添加到队列中 我已经重写了线程池执行程序的java 1.5版本的执行方法。 新守则如下:- 遗留代码如下所示:- 现在正

    • 我有一个应用程序,允许用户批量向图像添加水印。该应用程序将只使用一个线程,并且一次只能添加一个水印。 我希望用户能够更改一次运行的水印任务[线程]的数量:可能在设置中为[1-5],并且我不能使用固定的ThreadPool,因为它具有固定的池大小。 我研究了如何使用线程池执行器(ThreadPoolExecutor)私有静态线程池执行器(ThreadPoolExecutor)=(ThreadPool

    • ConsumptionExecutor: 然而,我想使用Akka流/Akka Actor,在这里我不需要给出固定的线程池大小,Akka负责所有的事情。我对Akka和流媒体和演员的概念很陌生。有人能给我任何线索,以示例代码的形式,以适合我的用例?提前道谢!

    • 我需要帮助设计基于多线程的应用程序,包括动态url创建和线程处理。 我在我的应用程序中使用了一个Spring调度器,它每30秒调度一次。从这个调度方法中,我调用了一些基于服务的api,它在循环中,而且我需要每个API有一个线程池执行器,上面有一个线程处理。 由于这个过程是从计划方法开始的,所以每次创建新的线程池时,这就是问题所在。你可以在代码中看到。 我想要的是,如果对于任何一个应用编程接口,如果