2013-01-09 2 views
19

얼마나 자주 액세스했는지에 대한 카운터 역할을하는 bean을 작성해야합니다. 동시에 여러 요청을 고려할 때 확인된다JEE6 @ApplicationScoped bean and concurrency

@ApplicationScoped 
class VisitsCounter { 

    private AtomicInteger counter; 

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

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

내 질문처럼 AtomicInteger@ApplicationScoped 콩을 사용한다 생각 해요? 또는 @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의 상태가 변경되었을 때 병행 주석과 잠금을 사용해야하지만 내 목록이 이미 스레드 안전을 처리한다면 어떻게 될까요?

+2

구현 된대로 동시성 문제가 발생하지 않습니다. – McDowell

답변

31

CDI에서는 동시성 관리가 없기 때문에 @ApplicationScoped은 단순히 주입 된 개체의 카디널리티를 나타냅니다 (즉, 빈의 인스턴스를 하나만 만들고 모든 응용 프로그램에서 사용하도록 주입 엔진에 지시 함). EJB에서 bean을 변환하지 않으며 동시성 제한을 시행하지 않습니다.

예에서 조작은 본질적으로 스레드 안전하지만 AtomicInteger 및 동기화 된 목록 덕분에 일반적으로 사실이 아닙니다. 당신이 할 수있는 일반적

:

  • 수동으로 목록을 동기화는

  • 또는가 응용 프로그램 서버를 지시 javax.ejb.Singleton 주석을 사용 (당신이했던 것처럼) 표준 동시성 프리미티브를 통해 액세스 동시성을 관리하십시오. 이렇게하면 EJB에서 bean을 변환하고 기본적으로 @ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)@Lock(LockType.WRITE)을 적용합니다. 그런데

, @ConcurrencyManagement@Lock은 싱글 세션 빈에서만 사용할 수 있습니다.

+0

좋습니다. '@Statementful' EJB에'@ApplicationScoped' 빈을 삽입하면 어떻게됩니까? 문제가 발생할 수있는 것처럼 보입니다. EJB의 두 인스턴스에서 동일한 데이터를 수정할 수 있기 때문입니다. – dalvarezmartinez1