我正在使用Thread Pool Executor改变遗留设计。详情如下: -
传统: - 在传统设计的情况下,在应用程序启动时创建600个线程。 并放置在各种池中,然后在需要时将其拾取并将任务分配给相应的线程。
新: - 在新设计中,我将执行程序服务替换为线程池
ThreadPoolExecutor thpool = new ThreadPoolExecutor(coreSize,poolsize,...);
我观察到的是,在Executor的情况下,在启动时没有创建线程。它们是在从客户端触发请求时创建的。因此,与前一个相比,在内存中创建的线程要少得多。
但我的问题是它是正确的方式,因为线程创建也是在触发调用时发生的开销。
请告诉哪个更重,根据传统方法处理客户端或空闲线程在内存中调用时的线程创建。
还建议使用哪个Executor池,以便在性能方面获得最佳结果。
答案 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)
Runnables
。假设您的线程平均负载为nCPUs=Runtime.getRuntime().availableProcessors()
和loadFactor
(在测试中观察到,或者更好的是,持续监控)。然后你将使用nThreads = nCPUs / loadFactor并希望loadFactor不为零。
您还可以使用较小的核心大小和较大的池化,但是您需要一个有界队列。在这种情况下,如果队列已满,则TPE将启动新线程,直到达到池化。如果大多数作业都是在coresize中处理的,那么创建线程不应该太频繁,并且开销不应该是一个问题。但是,当TPE最大线程运行时,即使这可能最终也会阻塞。
如果您的作业是某种传入工作,例如从其他连接的套接字中读取而不能阻止,您可以创建一个无限制的中间队列来释放入站处理,最终阻止您的TPE,并使用另一个线程提交从中间到TPE队列的作业。