我已经定义了一个bean,它需要在@PostConstruct生命周期阶段(启动期间)执行一些繁重的处理。
目前,我提交一个新的可调用的执行器服务,每次迭代处理循环。我将这些提交的未来对象的列表保存在一个成员变量中。
@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,它允许我检测应用程序何时完成启动。我使用这个处理程序循环遍历“期货”列表,并调用阻塞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将实现与向executor服务提交任务相同的目的吗?有没有一种方法可以将现有的executor服务传递到并行流中,以便它使用我为bean定义的线程池大小?
其次..。作为处理的一部分..。读取actionMappings地图,并将条目放入其中。它足以使这个映射成为一个ConcurrentHashMap,使它在这个场景中线程安全吗?
其次,实现ApplicationListener接口和侦听ContextRefreshedEvent是检测应用程序何时启动从而通过阻塞强制完成未处理任务的最佳方法吗?或者可以换一种方法?
谢谢。
发布于 2015-09-26 13:48:56
parallelStream():不行,这正是使用这种方法的主要缺点。只有在线程池大小不重要时才应该使用它,所以我认为您的ExecutorService-based方法很好。
由于您使用的是Java 8,所以您还可以使用CompletableFuture.supplyAsync()方法,它的重载需要一个Executor。因为ExecutorService扩展了Executor,所以您可以将ExecutorService传递给它,这样就完成了!ConcurrentHashMap是好的。它确保线程在其所有操作中的安全性,特别是在添加或修改条目的时候。ContextRefreshedEvent什么时候被解雇?根据Javadoc:
在初始化或刷新ApplicationContext时引发的。这并不保证您的onApplicationEvent()方法只被调用一次,也就是当您的bean被正确初始化时,这包括执行@PostConstruct-annotated方法。
我建议您实现BeanPostProcessor接口,并将Future-checkup逻辑放在postProcessAfterInitialization()方法中。两个BeanPostProcessor方法分别在InitializingBean.afterPropertiesSet()方法之前和之后调用(如果存在的话)。
我希望这会有帮助..。
干杯,
杰夫
https://stackoverflow.com/questions/32796922
复制相似问题