gpt4 book ai didi

java - 使用 Spring 在 Tomcat 启动期间委托(delegate)处理

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:57:32 25 4
gpt4 key购买 nike

我定义了一个 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 接口(interface),因此它可以监听 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 接口(interface)并监听 Co​​ntextRefreshedEvent 是否是检测应用程序何时启动并因此通过阻塞强制完成未处理任务的最佳方式?或者可以用其他方式完成吗?

谢谢。

最佳答案

  1. 关于使用parallelStream():没有,而这恰恰是使用这种方法的主要缺点。仅当线程池大小无关紧要时才应使用它,因此我认为您基于 ExecutorService 的方法很好。

    由于您使用的是 Java 8,因此您也可以使用 CompletableFuture.supplyAsync() 方法,该方法具有采用 Executor 的重载。由于 ExecutorService 扩展了 Executor,您可以将您的 ExecutorService 传递给它,您就完成了!

  2. 我认为 ConcurrentHashMap 很好。它确保所有操作的线程安全,尤其是在添加或修改条目时。

  3. ContextRefreshedEvent 何时触发?根据 Javadoc:

    Event raised when an ApplicationContext gets initialized or refreshed.

    这不能保证您的 onApplicationEvent() 方法被调用一次且仅一次,也就是说,当您的 bean 被正确初始化时,包括 @PostConstruct< 的执行-带注释的方法。

    我建议您实现 BeanPostProcessor 接口(interface)并将您的 Future - 检查逻辑放在 postProcessAfterInitialization() 方法中。这两个 BeanPostProcessor 方法分别在 InitializingBean.afterPropertiesSet() 方法(如果存在)之前和之后调用。

我希望这会有所帮助...

干杯,

杰夫

关于java - 使用 Spring 在 Tomcat 启动期间委托(delegate)处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32796922/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com