【发布时间】:2015-09-26 11:57:32
【问题描述】:
我已经定义了一个 bean,它需要在 @PostConstruct 生命周期阶段(在启动期间)进行一些繁重的处理。
就目前而言,我在处理循环的每次迭代中向执行器服务提交一个新的 Callable。我将这些提交返回的 Future 对象列表保存在成员变量中。
@Component
@Scope("singleton")
public class StartupManager implements ApplicationListener<ContextRefreshedEvent> {
@Autowired
private ExecutorService executorService;
private final Map<Class<?>, Optional<Action>> actionMappings = new ConcurrentHashMap<>();
private final List<Future> processingTasks = Collections.synchronizedList(new ArrayList<>());
@PostConstruct
public void init() throws ExecutionException, InterruptedException {
this.controllers.getHandlerMethods().entrySet().stream().forEach(handlerItem -> {
processingTasks.add(executorService.submit(() -> {
// processing
}));
});
}
}
同样的 bean 实现了 ApplicationListener 接口,因此它可以侦听 ContextRefreshedEvent,它允许我检测应用程序何时完成启动。我使用这个处理程序来遍历 Futures 列表并调用阻塞的 get 方法,以确保在应用程序继续之前所有的处理都已经发生。
@Override
public void onApplicationEvent(ContextRefreshedEvent applicationEvent) {
for(Future task : this.processingTasks) {
try {
task.get();
} catch (InterruptedException | ExecutionException e) {
throw new IllegalStateException(e.getMessage());
}
}
}
我的第一个问题... 将 actionMapping 流更改为 parallelStream 是否与将任务提交给执行器服务相同?有没有办法可以将现有的执行程序服务传递到并行流中,以使用我为 bean 定义的线程池大小?
其次.. 作为处理的一部分.. 读取 actionMappings 映射并将条目放入其中。在这种情况下,让这个 Map 成为 ConcurrentHashMap 以使其线程安全就足够了吗?
其次是实现 ApplicationListener 接口并侦听 ContextRefreshedEvent 是检测应用程序何时启动并因此通过阻塞强制完成未处理任务的最佳方法吗?或者这可以通过其他方式完成吗?
谢谢。
【问题讨论】:
标签: java multithreading spring tomcat