Java 线程池执行器

Java 线程池执行器,java,multithreading,threadpool,Java,Multithreading,Threadpool,我正在使用线程池执行器改变传统设计。详情如下:- 遗留:-对于遗留设计,在应用程序启动时创建600个线程。 和放置在不同的池中,然后在需要时提取这些池,并将任务分配给相应的线程 新:-在新设计中,我将线程池替换为executor服务 ThreadPoolExecutor thpool = new ThreadPoolExecutor(coreSize,poolsize,...); 我所观察到的是,对于Executor,在启动时不会创建线程。它们是在从客户端激发请求时创建的。因此,在内存中创建

我正在使用线程池执行器改变传统设计。详情如下:-

遗留:-对于遗留设计,在应用程序启动时创建600个线程。 和放置在不同的池中,然后在需要时提取这些池,并将任务分配给相应的线程

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

 ThreadPoolExecutor thpool = new ThreadPoolExecutor(coreSize,poolsize,...);
我所观察到的是,对于Executor,在启动时不会创建线程。它们是在从客户端激发请求时创建的。因此,在内存中创建的线程与前一个线程相比要少得多

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

请告诉我哪一个更重,在客户端调用时创建进程线程,还是按照传统方法在内存中创建空闲线程


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

要在启动时修复600个线程,请尝试使用

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

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

如果您想要启动时启动的600个线程,您可以发布600个空任务:

for( int i = 0; i < 600; ++i ) {
   executor.submit( new Runnable(){public void run(){/**/}});
}
for(int i=0;i<600;++i){
submit(new Runnable(){public void run(){/***}});
}
您可以拨打:

thpool.prestartAllCoreThreads();

这两种方法用于启动核心线程(线程),使其空闲等待工作


但我建议不要这样做,这将直接占用您的资源。

600听起来太多了。您可能希望将其降低到可用处理器的数量。或者,如果线程最终等待了很长时间,那么如果您的线程没有100%的CPU限制,那么TPE的
可运行文件将是导致平均负载的一个因素。假设您将
nCPUs=Runtime.getRuntime().availableProcessor()
loadFactor
作为线程上的平均负载(如测试中所观察到的,或者更好的是,连续监视中所观察到的)。然后使用nThreads=nCPUs/loadFactor,希望loadFactor不是零

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


如果您的作业是某种传入的作业,例如从其他连接的套接字读取,而该套接字不能阻塞,那么您可以创建一个无界的中间队列,以释放入站处理,使其最终不会在您的TPE上阻塞,并使用另一个线程将作业从中间提交到TPE队列。

我们如何计算所需的线程数u猜想我们有一个公式:-CPU数*性能吞吐量*(1+W/C),其中W是等待时间,C是所需计算时间。请详细告诉我如何获得所需的线程数。不确定您的性能吞吐量是多少,但请参阅我的编辑。嗨,拉尔夫,谢谢您的输入。好吧,但我已经进入了一个修复。我创建了一个ThreadPoolExecutor,其核心大小为maxpoolsize/5,并使用LinkedBlockingQueue作为队列。我调用了方法“prestartAllCoreThreads”,该方法在启动时启动大约170个核心线程。我这样做的原因是,当我从客户端发出请求时,executor创建了一个新线程,该线程正在消耗时间,所以我想取消此选项。但这种做法适得其反。与旧代码相比,内存消耗有所增加,旧代码在处理请求方面,我也找不到明显的性能改进。关于来自客户端的任务,我应该告诉你,我正在做的是从客户端提供一个设备IP,然后服务器向该设备发送RMI命令。任务从我创建的线程池中分配了一个线程。请告诉我我的方法哪里出了问题,以及如何使用执行器优化此行为。谢谢和问候,图萨
thpool.prestartCoreThread();