2015-11-17 16 views
7

我努力實現以下目標:EJB @Asynchronous檢索實時插入行中JSF似乎是線程鎖定

EJB3辛格爾頓

@Singleton 
@Startup 
public class SomeSingleton implements SomeSingletonLocal { 

    // Entity Manager injection 
    private EntityManager _entity_manager; 

    @Override 
    @Asynchronous 
    public void createScenario(){ 
     method1(); 
     method2(); 
     // ... 
    } 

    public void method1(){ 
     // Persist an Event in a Database. 
    } 

    public void method2(){ 
     // Persist an Event in a Database. 
    } 

} 

Managed Bean的

@ManagedBean 
@RequestScoped 
public class SomeManagedBean{ 

    // Entity Manager injection 
    private EntityManager _entity_manager; 

    @EJB 
    private SomeSingletonRemote _singleton; 

    public void createScenario(){ 
     _singleton.createScenario(); 
    } 

    public List<Event> getEventList(){ 
     // Retrieve events from database 
    } 
} 

JSF視圖

<h:form> 
    <p:commandButton value="Start Long Stuff" 
     actionListener="#{SomeManagedBean.createScenario}" /> 
    <h:outputText id="count" value="#{SomeManagedBean.getEventList.size()}" /> 
      <p:poll interval="1" update="count" /> 
</h:form> 

日誌

- > SomeManagedBean.getEventList()
< -SomeManagedBean.getEventList()//大小= 0

//布頓點擊
- > SomeManagedBean .createScenario()
            - > SomeSingleton.createScenario()
< -SomeManagedBean.createScenario()

- > SomeManagedBean.getEventList()//將在SomeSingleton.createScenario
的結束而終止 - > SomeSingleton.method1()
< -SomeSingleton.method1()//堅持
...
- > SomeSingleton.methodN()
< -SomeSingleton.methodN()//堅持

< -SomeSingleton.createScenario()

< -SomeManagedBean.getEventList()//大小= N

我預期至少一個呼叫兩個methodI()調用之間getEventList(即。每秒)。當它進入SomeSingleton.createScenario()時,我不知道爲什麼getEventList被暫停。

它看起來像是實體管理器或createScenario內部的事務處理鎖。這是一個再入口問題嗎?

回答

8

A @Singleton確實默認爲讀/寫鎖定。這不是與事務嚴格相關,而是與併發有關。另見a.o. Java EE 7 tutorial on the subject

解決此問題的一種方法是將@ConcurrencyManagement設置爲BEAN。通過這種方式,您基本上可以告訴容器不必擔心併發性,並且您自己承擔全部責任。

@Singleton 
@ConcurrencyManagement(ConcurrencyManagementType.BEAN) 
public class SomeSingleton {} 

另一種方式是明確設置@LockREAD的類或只讀的方法,使他們可以同時調用。只有在同一個實例上調用一個顯式爲@Lock(LockType.WRITE)的方法時,纔會發生鎖定。

@Singleton 
@Lock(LockType.READ) 
public class SomeSingleton {} 
+0

爲什麼他們[提及](https://docs.oracle.com/javaee/7/tutorial/ejb-basicexamples002.htm),「*如果沒有'@ Lock'註釋存在於單類,默認鎖類型「@Lock(LockType.WRITE)'應用於所有業務和超時方法*」? – Tiny

+0

@Tiny:您能否澄清一下您對哪一部分不清楚?它基本上說,當類沒有'@ Lock'註釋時,所有方法默認爲'@Lock(LockType.WRITE)'。這也包括在答案中(但可能有點不明確,我想根據你的反饋改進那部分)。 – BalusC

+0

這些粗體字母在這裏:「* A'@ Singleton'實際上默認是**讀/寫鎖定***」。 (對不起,我最初得到的印象不是很準確,單身EJB有默認的「讀」和「寫」鎖,這樣,改變狀態的方法應該默認爲「寫」鎖定,其餘的,如果有的話,不改變狀態應該是「讀取」默認鎖定)。 – Tiny