我需要编写一个 bean 来作为它被访问次数的计数器。
我正在考虑将 @ApplicationScoped
bean 与 AtomicInteger
一起使用
@ApplicationScoped
class VisitsCounter {
private AtomicInteger counter;
@PostConstruct
public void construct() {
counter = new AtomicInteger(0);
}
public int visited() {
return counter.incrementAndGet();
}
}
我的问题是:同时考虑多个请求时可以吗?还是我需要使用 @ConcurrencyManagement
和 @Lock
注释?我想 Atomic*
应该可以解决问题,但我不确定。
当我将线程安全集合作为字段时,同样适用吗?例如。说我有
@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
只是说明注入(inject)对象的基数(即指示注入(inject)引擎只创建一个 bean 实例并在所有实例中使用它应用程序)。它不会在 EJB 中转换您的 bean,也不会强制执行任何并发约束。
因此,虽然示例中的操作本质上是线程安全的,但由于 AtomicInteger
和同步列表,通常情况并非如此。
一般来说你可以:
通过标准并发原语手动同步列表访问(正如您所做的那样)
或使用
javax.ejb.Singleton
注解,指示应用服务器管理并发。这会在 EJB 中转换您的 bean,默认情况下强制执行@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
和@Lock(LockType.WRITE)
。
顺便说一下,@ConcurrencyManagement
和 @Lock
仅在单例 session bean 上可用。
关于java - JEE6 @ApplicationScoped bean 和并发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14237499/