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
而不是 Executors
1 中的 ExecutorService
,那么可能会有更多 standard/supported 立即启动所有核心线程的方法。
int nThreads = 200;
ThreadPoolExecutor executor = new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
executor.prestartAllCoreThreads();
请注意,目前,Executors.newFixedThreadPool(int)
的实现以与上述完全相同的方式创建了一个 ThreadPoolExecutor
。这意味着您可以在技术上将工厂方法编辑的 ExecutorService
return 转换为 ThreadPoolExecutor
。然而,文档中没有任何内容 保证 它将是 ThreadPoolExecutor
。
1. ThreadPoolExecutor
实现了 ExecutorService
但提供了更多功能。此外,Executors
中的许多工厂方法直接 return 是 ThreadPoolExecutor
或委托给一个的包装器。有些,例如 newWorkStealingPool
,使用 ForkJoinPool
。同样,这些工厂方法的 return 类型是实现细节,因此不要过分依赖它。
当我的应用程序启动时,会创建一个执行程序服务(使用 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
而不是 Executors
1 中的 ExecutorService
,那么可能会有更多 standard/supported 立即启动所有核心线程的方法。
int nThreads = 200;
ThreadPoolExecutor executor = new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
executor.prestartAllCoreThreads();
请注意,目前,Executors.newFixedThreadPool(int)
的实现以与上述完全相同的方式创建了一个 ThreadPoolExecutor
。这意味着您可以在技术上将工厂方法编辑的 ExecutorService
return 转换为 ThreadPoolExecutor
。然而,文档中没有任何内容 保证 它将是 ThreadPoolExecutor
。
1. ThreadPoolExecutor
实现了 ExecutorService
但提供了更多功能。此外,Executors
中的许多工厂方法直接 return 是 ThreadPoolExecutor
或委托给一个的包装器。有些,例如 newWorkStealingPool
,使用 ForkJoinPool
。同样,这些工厂方法的 return 类型是实现细节,因此不要过分依赖它。