Java 应用程序启动时执行程序服务启动线程

Java Executor Service Start Threads when Application Launches

当我的应用程序启动时,会创建一个执行程序服务(使用 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 个线程。

只是想知道这是在应用程序启动时创建线程的正确方法吗? 或者有更好的方法吗?

可以运行 并行的线程数取决于您的处理器内核。除非你有 200 个内核,否则创建 200 个线程池将毫无用处。

了解您拥有多少个处理器核心的好方法是:

int cores = Runtime.getRuntime().availableProcessors();

此外,在创建新线程和执行它的过程中产生的开销是不可避免的,因此除非任务的计算量很大,否则不值得为此任务创建一个新的单线程。

但毕竟到目前为止您的代码完全没问题。

如果您的代码适用于您的场景,那么您的代码就完全没问题。由于我们不知道您的用例,只有您可以通过足够的测试和基准来回答您的问题。

但是请注意,ThreadPool 会在一段时间后回收空闲线程。如果你不注意它可能会咬你。

您缺少 shutdown()。操作完成后关闭 Executor 服务非常重要。所以有 try,catch and Finally block

try{ executorService.execute(...); }catach(Exception e){ ... }finally{ executorService.shutdown(); //Mandatory }

Just wonder is this a correct way of creating threads when application starts?

是的。这是创建线程的正确方法。

Or is there a better way of doing it?

也许吧。在某些工作负载下,您可能希望使用具有可变线程数的线程池(与 newFixedThreadPool 创建的线程不同)- 从池中删除已空闲一段时间的线程。

如果您可以直接使用 ThreadPoolExecutor 而不是 Executors1 中的 ExecutorService,那么可能会有更多 standard/supported 立即启动所有核心线程的方法。

int nThreads = 200;
ThreadPoolExecutor executor = new ThreadPoolExecutor(nThreads, nThreads, 
        0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
executor.prestartAllCoreThreads();

以上使用prestartAllCoreThreads().

请注意,目前,Executors.newFixedThreadPool(int) 的实现以与上述完全相同的方式创建了一个 ThreadPoolExecutor。这意味着您可以在技术上将工厂方法编辑的 ExecutorService return 转换为 ThreadPoolExecutor。然而,文档中没有任何内容 保证 它将是 ThreadPoolExecutor


1. ThreadPoolExecutor 实现了 ExecutorService 但提供了更多功能。此外,Executors 中的许多工厂方法直接 return 是 ThreadPoolExecutor 或委托给一个的包装器。有些,例如 newWorkStealingPool,使用 ForkJoinPool。同样,这些工厂方法的 return 类型是实现细节,因此不要过分依赖它。