JEE6 @ApplicationScoped豆和并发

2022-09-01 20:35:01

我需要写一个bean,作为它被访问了多少次的计数器。

我正在考虑用这样的豆子@ApplicationScopedAtomicInteger

@ApplicationScoped
class VisitsCounter {

    private AtomicInteger counter;

    @PostConstruct
    public void construct() {
        counter = new AtomicInteger(0);
    }

    public int visited() {
        return counter.incrementAndGet();
    }
}

我的问题是:同时考虑多个请求可以吗?还是我需要玩和注释?我想这应该可以解决问题,但我不确定。@ConcurrencyManagement@LockAtomic*

此外,当我将线程安全集合作为字段时,是否也适用?例如,说我有

@ApplicationScoped
class ValuesHolder {

    private List<String> values;

    @PostConstruct
    public void construct() {
        values = Collections.synchronizedList(new LinkedList<String>());
    }

    public void insert(String value) {
        values.add(value);
    }

    public String remove(String value) {
        return values.remove(value);
    }
}

操作真的是线程安全的吗?

据说在修改Bean的状态时应该使用并发注释和锁,但是如果我的列表已经解决了线程安全怎么办?


答案 1

在CDI中,你没有并发管理,所以简单地说明注入对象的基数(即指示注入引擎只创建一个bean实例,并在所有应用程序中使用它)。它不会在 EJB 中转换您的 Bean,也不会强制实施任何并发约束。@ApplicationScoped

因此,虽然示例中的操作本质上是线程安全的,但由于 和 同步列表,一般来说情况并非如此。AtomicInteger

在一般情况下,您可以:

  • 通过标准并发基元手动同步列表访问(如您所做)

  • 或者使用注释,它指示应用程序服务器管理并发性。这将在 EJB 中转换 Bean,并且缺省情况下强制实施 和 。javax.ejb.Singleton@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)@Lock(LockType.WRITE)

顺便说一句,并且仅在单例会话bean上可用。@ConcurrencyManagement@Lock


答案 2

推荐