EJB @Asynchronous在JSF中检索实时插入的行似乎是线程锁定的

Cha*_*let 7 concurrency jsf asynchronous ejb java-ee

我想要实现以下目标:

EJB3 Singleton

@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.
    }

}
Run Code Online (Sandbox Code Playgroud)

管理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
    } 
}
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

日志

- > SomeManagedBean.getEventList()
< - SomeManagedBean.getEventList()// Size = 0

// Buton点击
- > SomeManagedBean.createScenario()
      - > SomeSingleton.createScenario()
< - SomeManagedBean.createScenario()

- > SomeManagedBean.getEventList()//将在SomeSingleton.createScenario结束时结束
- > SomeSingleton.method1()
< - SomeSingleton.method1()// persist
...
- > SomeSingleton.methodN()
< - SomeSingleton.methodN ()//坚持

<-SomeSingleton.createScenario()

<-SomeManagedBean.getEventList()// size = N.

我期望在两个methodI()调用(即每秒)之间至少调用一次getEventList.当它进入SomeSingleton.createScenario()时,我不知道为什么getEventList被暂停.

看起来实体管理器或createScenario中的事务存在锁定.这是一个重入问题吗?

Bal*_*usC 8

A @Singleton确实默认为读/写锁定.这与事务并不严格相关,而是与并发性有关.另请参阅有关该主题的 ao Java EE 7教程.

解决它的一种方法是设置@ConcurrencyManagementBEAN.通过这种方式,您基本上可以告诉容器根本不用担心并发问题,并且您自己承担所有责任.

@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class SomeSingleton {}
Run Code Online (Sandbox Code Playgroud)

另一种方法是显式设置@LockREAD类或只读方法,以便可以同时调用它们.仅当@Lock(LockType.WRITE)在同一实例上调用具有显式的方法时,才会发生锁定.

@Singleton
@Lock(LockType.READ)
public class SomeSingleton {}
Run Code Online (Sandbox Code Playgroud)

  • @Tiny:`@Lock(READ)`确实是一种误导性的名称,因为它基本上意味着该方法变得不同步而不是同步(即调用方法时没有任何内部锁定的方法).但是,当调用`@Lock(WRITE)`方法时,整个实例都会被锁定,包括对@Lock(READ)`方法的所有访问. (2认同)