java - CDI PostConstruct 和可变字段

标签 java jakarta-ee concurrency cdi volatile

当我们想要有条件地初始化一些 bean 的字段时使用后构造方法,我们是否需要关心字段的波动性,因为它是一个多线程环境?

比如说,我们有这样的东西:

@ApplicationScoped
public class FooService {

    private final ConfigurationService configurationService;

    private FooBean fooBean;

    @Inject
    FooService(ConfigurationService configurationService) {
         this.configurationService = configurationService;
    }

    void init(@Observes @Initialized(ApplicationScoped.class) Object ignored) {
        if (configurationService.isFooBeanInitialisationEnabled()) {
             fooBean = initialiseFooBean(configurationService); // some initialisation
        }
    }

    void cleanup(@Observes @Destroyed(ApplicationScoped.class) Object ignored) {
       if (fooBean != null) {
           fooBean.cleanup();
       }
    }
}

那么 fooBean 应该被包装到比方说 AtomicReference 中还是 volatile 或者它会是一个多余的额外保护?

P.S. 在这种特殊情况下,它可以重新表述为:post construct 和 post destroy 事件是否由同一线程执行?但是,我想对更一般的情况有一个答案。

最佳答案

我会说这取决于哪个线程实际启动和销毁上下文。 如果您使用常规事件,它们是同步的(异步事件已添加到 CDI 2.0 中,带有 ObservesAsync,请参阅 Java EE 8: Sending asynchronous CDI 2.0 events with ManagedExecutorService ) 因此它们在与调用者相同的线程中被调用。

一般来说,我不认为使用相同的线程(在应用程序服务器或独立应用程序中)所以我建议使用 volatile 来确保看到正确的值(基本上是看到构造的值在销毁线程)。但是,以并发方式启动和销毁您的应用程序并不是经常发生的用例...

关于java - CDI PostConstruct 和可变字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53227585/

相关文章:

language-agnostic - 是否有针对这些特定多线程数据结构要求的现有解决方案?

java - @FindBy 注解定义的 Webelement 返回空指针

java - 为某些玩家隐藏实体 - Spigot/Bukkit - Java

java - 如何动态更改文本框中文本的大小

java - 写入maven项目中的文件

java - 为什么 LogWriter 中的竞争条件会导致生产者阻塞? [实践中的并发]

java - Gradle 多项目构建命令失败但对子项目正常工作

java - 一对一和连接表

JPA NativeQuery 中的 MYSQL 嵌套查询

java - 线程安全的程序如何包含非线程安全的类?