JEE6 @ApplicationScoped bean 和并发
Posted
技术标签:
【中文标题】JEE6 @ApplicationScoped bean 和并发【英文标题】:JEE6 @ApplicationScoped bean and concurrency 【发布时间】:2012-12-23 15:14:13 【问题描述】:我需要编写一个 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的状态发生修改时应该使用并发注解和锁,但是如果我的列表已经照顾了线程安全呢?
【问题讨论】:
实施后,我没有看到任何并发问题。 【参考方案1】:在 CDI 中,您没有并发管理,因此 @ApplicationScoped
仅声明注入对象的基数(即指示注入引擎仅创建 bean 的一个实例并在所有应用程序中使用它)。它不会在 EJB 中转换您的 bean,也不会强制执行任何并发约束。
因此,虽然示例中的操作本质上是线程安全的,但由于 AtomicInteger
和同步列表,通常情况并非如此。
一般来说你可以:
通过标准并发原语手动同步列表访问(正如您所做的那样)
或者使用javax.ejb.Singleton
注解,指示应用服务器管理并发。这会将您的 bean 转换为 EJB,默认情况下强制执行 @ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
和 @Lock(LockType.WRITE)
。
顺便说一下,@ConcurrencyManagement
和 @Lock
仅适用于单例会话 bean。
【讨论】:
好一个。我在想如果我将@ApplicationScoped
bean 注入@Stateful
EJB 会发生什么,看起来你可能会遇到问题,因为你可以从 EJB 的 2 个实例中修改相同的数据。
字段(counter
、values
)是否保证可见?毕竟它们是由不同的线程访问的,没有任何并发机制。以上是关于JEE6 @ApplicationScoped bean 和并发的主要内容,如果未能解决你的问题,请参考以下文章
JavaEE6 DAO:应该是@Stateless 还是@ApplicationScoped?
多次构造 Eager ApplicationScoped 托管 bean