启动我的应用程序时,将创建执行程序服务(使用java.util.concurrent中的Executors.newFixedThreadPool(maxThreadNum))。当请求到来时,执行程序服务将创建线程来处理它们。
由于在运行时创建线程需要花费时间,因此我想在启动应用程序时使线程可用,以便在请求到来时处理时间减少。
我所做的是:
executorService = Executors.newFixedThreadPool(200);
for (int i=0; i<200; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println("Start thread in pool " );
}
});
}
当应用程序启动时,它将在executorService池中创建200个线程。
只想知道这是应用程序启动时创建线程的正确方法吗? 还是有更好的方法呢?
答案 0 :(得分:3)
您缺少shutdown()
。完成操作后,关闭Executor服务非常重要。 try,catch and Finally block
try{
executorService.execute(...);
}catach(Exception e){
...
}finally{
executorService.shutdown(); //Mandatory
}
答案 1 :(得分:2)
如果您可以直接使用ThreadPoolExecutor
而不是ExecutorService
1 中的Executors
,那么可能有更标准/受支持的方式来启动所有立即成为核心线程。
int nThreads = 200;
ThreadPoolExecutor executor = new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
executor.prestartAllCoreThreads();
请注意,目前,Executors.newFixedThreadPool(int)
的实现以与上述完全相同的方式创建了ThreadPoolExecutor
。这意味着您可以从技术上将工厂方法返回的ExecutorService
强制转换为ThreadPoolExecutor
。但是,文档中没有任何内容可以保证 为ThreadPoolExecutor
。
1。 ThreadPoolExecutor
实现了ExecutorService
,但提供了更多功能。同样,Executors
中的许多工厂方法要么直接返回ThreadPoolExecutor
,要么返回委托给它的包装器。有些newWorkStealingPool
等使用ForkJoinPool
。同样,这些工厂方法的返回类型是实现细节,因此请不要过于依赖它。
答案 2 :(得分:1)
可以并行运行的线程数取决于您的处理器内核。除非您有200个内核,否则创建200个线程池将毫无用处。
找出拥有多少处理器核心的好方法是:
int cores = Runtime.getRuntime().availableProcessors();
此外,在创建新线程并执行该线程时所产生的开销是不可避免的,因此,除非对该任务进行大量计算,否则不值得为此任务创建新的单线程。
但是到目前为止,您的代码毕竟还不错。
答案 3 :(得分:1)
如果您的代码适用于您的情况,则完全可以。由于我们不知道您的用例,因此只有您可以使用足够的测试和基准来回答您的问题。
但是,请注意,ThreadPool将在一段时间后回收空闲线程。如果您不注意它,那可能会咬你。
答案 4 :(得分:0)
请问这是应用程序创建线程的正确方法吗? 开始吗?
是的。这是创建线程的正确方法。
还是有更好的方法呢?
也许。在某些工作负载下,您可能希望使用具有可变数量线程的线程池(与newFixedThreadPool
创建的线程池不同)-一种线程池从池中移出已闲置了一段时间的线程。