Java JEE6@ApplicationScoped bean和并发

Java JEE6@ApplicationScoped bean和并发,java,jakarta-ee,concurrency,cdi,Java,Jakarta Ee,Concurrency,Cdi,我需要编写一个bean,作为访问次数的计数器 我正在考虑将@ApplicationScoped bean与原子整数一起使用 @ApplicationScoped class VisitsCounter { private AtomicInteger counter; @PostConstruct public void construct() { counter = new AtomicInteger(0); } public int

我需要编写一个bean,作为访问次数的计数器

我正在考虑将@ApplicationScoped bean与原子整数一起使用

@ApplicationScoped
class VisitsCounter {

    private AtomicInteger counter;

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

    public int visited() {
        return counter.incrementAndGet();
    }
}
我的问题是:当同时考虑多个请求时可以吗?或者我需要使用@concurrentymanagement和@Lock注释吗?我想原子弹应该会起作用,但我不确定

当我将线程安全集合作为一个字段时,是否也同样适用?比如说我有

@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的状态时应该使用并发注释和锁,但是如果我的列表已经考虑了线程安全怎么办?

在CDI中,您没有并发管理,因此@ApplicationScoped只是说明注入对象的基数,即指示注入引擎只创建bean的一个实例,并在所有应用程序中使用它。它不会在EJB中转换bean,也不会强制执行任何并发约束

因此,尽管由于AtomicInteger和synchronized list,示例中的操作本质上是线程安全的,但通常情况下并非如此

一般来说,您可以:

如您所做的那样,通过标准并发原语手动同步列表访问

或者使用javax.ejb.Singleton注释,它指示应用程序服务器管理并发性。这将在EJB中转换bean,并在默认情况下强制@ConcurrencyManagementConcurrencyManagementType.CONTAINER和@LockLockType.WRITE


顺便说一句,@concurrentymanagement和@Lock仅在单例会话bean上可用。

实现后,我看不到任何并发问题。很好。我在想,如果我将@ApplicationScoped bean注入@Stateful EJB,会发生什么情况,似乎您可能会遇到问题,因为从EJB的两个实例可以修改相同的数据。字段计数器、值是否保证可见?毕竟,它们是由不同的线程访问的,没有任何并发机制。