线程池执行器

时间:2013-09-29 08:59:41

标签: java multithreading threadpool

我正在使用Thread Pool Executor改变遗留设计。详情如下: -

传统: - 在传统设计的情况下,在应用程序启动时创建600个线程。 并放置在各种池中,然后在需要时将其拾取并将任务分配给相应的线程。

新: - 在新设计中,我将执行程序服务替换为线程池

 ThreadPoolExecutor thpool = new ThreadPoolExecutor(coreSize,poolsize,...);

我观察到的是,在Executor的情况下,在启动时没有创建线程。它们是在从客户端触发请求时创建的。因此,与前一个相比,在内存中创建的线程要少得多。

但我的问题是它是正确的方式,因为线程创建也是在触发调用时发生的开销。

请告诉哪个更重,根据传统方法处理客户端或空闲线程在内存中调用时的线程创建。

还建议使用哪个Executor池,以便在性能方面获得最佳结果。

3 个答案:

答案 0 :(得分:1)

在启动时修复600个线程,尝试使用java.util.concurrent.Executors.newFixedThreadPool( 600 );

  

创建一个重用固定数量的线程的线程池   关闭共享的无界队列。在任何时候,最多nThreads线程   将是主动处理任务。如果提交了其他任务   当所有线程都处于活动状态时,它们将在队列中等待直到a   线程可用。如果任何线程由于故障期间终止而终止   在关机之前执行,如果需要,新的将取代它   执行后续任务。池中的线程将一直存在   它是明确关闭的。

正如您所看到的,文档没有告诉我们线程是立即启动还是按需启动。

如果你想在启动时完全启动600个线程,你可以发布600个空任务:

for( int i = 0; i < 600; ++i ) {
   executor.submit( new Runnable(){public void run(){/**/}});
}

答案 1 :(得分:0)

你可以致电:

thpool.prestartAllCoreThreads();

thpool.prestartCoreThread();

这两种方法启动一个核心线程(Threads),导致它无所事事地等待工作。

但我建议不要这样做,它将会占用你的资源。

答案 2 :(得分:0)

600听起来很多。您可能希望将此值稍微降低到可用处理器的数量。或者,如果线程最终等待很多,那么如果您的线程不是100%受CPU限制,那么引起的平均负载的因素是TPE的Runnables。假设您的线程平均负载为nCPUs=Runtime.getRuntime().availableProcessors()loadFactor(在测试中观察到,或者更好的是,持续监控)。然后你将使用nThreads = nCPUs / loadFactor并希望loadFactor不为零。

您还可以使用较小的核心大小和较大的池化,但是您需要一个有界队列。在这种情况下,如果队列已满,则TPE将启动新线程,直到达到池化。如果大多数作业都是在coresize中处理的,那么创建线程不应该太频繁,并且开销不应该是一个问题。但是,当TPE最大线程运行时,即使这可能最终也会阻塞。

如果您的作业是某种传入工作,例如从其他连接的套接字中读取而不能阻止,您可以创建一个无限制的中间队列来释放入站处理,最终阻止您的TPE,并使用另一个线程提交从中间到TPE队列的作业。