我有一个方法,必须处理数千个文档。
正常处理需要时间,所以我使用ExecutorService
通过让多个线程并行工作来减少处理时间。
我必须使用此方法处理两个长列表。
ExecutorService
的方法1:现在,我已在方法中初始化ExecutorService
并以相同方法关闭它。 (被叫两次)
因此,它会导致创建和关闭ExecutorService
两次。
private List<DocDTO> convertData(args) {
ExecutorService service = Executors.newFixedThreadPool(threads);
List<Future<Set<DocDTO>>> futures = new ArrayList<Future<Set<DocDTO>>>();
for (Pro pro : pros.getPros()) {
Callable<Set<DocDTO>> callable = new Callable<Set<DocDTO>>() {
public Set<DocDTO> call() throws Exception {
for loop code
}
};
futures.add(service.submit(callable));
}
service.shutdown();
for (Future<Set<DocDTO>> future : futures) {
if (future.get() != null) {
list.addAll(future.get());
}
}
}
ExecutorService
的方法2:我在看下面的链接:
http://programtalk.com/java/executorservice-not-shutting-down/
作者在班级创建了ExecutorService
。
请您告诉我是否最好在方法级或班级创建ExecutorService
?
仅供参考,上述代码中的方法每天执行两次
答案 0 :(得分:1)
自然选择是将此类服务设为类字段。
建立这样的服务不是免费的。你花了那笔费用来“构建”那个线程池;以及正确关闭它的时间 - 每次调用该方法时。
大多数时候,这不是你想要的。你想花一次时间(比如:当创建服务的对象被创建时)。
一个缺点:现在持有服务的班级的“生命时间”很重要。正如您现在可能必须担心显式调用shutdown()
该持有者类所拥有的服务。
换句话说:当您不得不担心性能时,您可能会将服务更改为类的字段。
但是:你明确声明这个方法每天被调用两次。然后,您绝对不必担心通过创建/关闭该服务而生成的开销。即使开销会导致1秒的计算时间 - 每天2秒也根本不重要。
所以,鉴于 要求 - 我的(个人)建议:保持你的代码不变。在出现真正的问题之前,请勿触摸正在运行的系统。
答案 1 :(得分:1)
首先,我建议您阅读此doc,了解如何使用spring启用任务执行程序服务。正如GhostCat正确建议的那样,它应该在类级别。我还建议为它创建一个单独的bean。
例如:
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
return executor;
}
我是从this回答得到的,但是你可以在互联网上找到很多不同的配置。
答案 2 :(得分:0)
感谢Maleen和GhostCat的宝贵意见,我放弃了使用多线程的计划,原因有两个:
从单线程和多线程运行时,我从同一方法得到不同的结果
ExecutorService不适用于Lazy关系。因此,将实体的负载从Lazy更改为Eager可能会影响其他功能性能
相反,我优化了加载实体的方式,而不是使用多线程。以前,我在for循环中逐个加载数据库中的所有静态数据并将其保存在EhCache中。
更改后,我使用findall方法一次性加载所有静态数据并保存在map中,并从for循环中的map中访问相同的数据。它大大提高了方法的性能。再次感谢你们两位。