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

在JSF中检索实时插入行的EJB@Asynchronous似乎是线程锁定的,jsf,jakarta-ee,asynchronous,concurrency,ejb,Jsf,Jakarta Ee,Asynchronous,Concurrency,Ejb,我正在努力实现以下目标: EJB3单例 @Singleton @Startup public class SomeSingleton implements SomeSingletonLocal { // Entity Manager injection private EntityManager _entity_manager; @Override @Asynchronous public void createScenario(){

我正在努力实现以下目标:

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

}
@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
    } 
}
托管Bean

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

}
@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
    } 
}
@ManagedBean
@请求范围
公共类SomeManagedBean{
//实体管理器注入
私人实体经理(实体经理),;
@EJB
私人SomeSingleton远程singleton;
公共场景(){
_createScenario();
}
公共列表getEventList(){
//从数据库检索事件
} 
}
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.createScenario()
->SomeSingleton.createScenario()
SomeManagedBean.getEventList()//将在SomeSingleton.CreateScaprio的末尾结束
->SomeSingleton.method1()
SomeSingleton.methodN()

默认情况下,
@Singleton
确实是读/写锁定的。这并不严格地与事务相关,而是与并发性相关。另见a.o

解决此问题的一种方法是将设置为。这样,您基本上告诉容器根本不用担心并发性,您自己承担所有责任

@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class SomeSingleton {}
另一种方法是在类或只读方法上显式设置为,以便可以并发调用它们。只有在同一实例上调用带有显式锁(LockType.WRITE)的方法时,才会发生锁

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

为什么他们会说,“如果singleton类上没有
@Lock
注释,那么默认的锁类型,
@Lock(LockType.WRITE)
,将应用于所有的业务和超时方法”@Tiny:您能澄清一下您不清楚的部分吗?它基本上说,当类上没有
@Lock
注释时,所有方法都默认为
@Lock(LockType.WRITE)
。答案中也包括了这一点(但可能有点不清楚,我想根据您的反馈改进这一部分)。这里的粗体字母是:“a
@Singleton
在默认情况下确实是读/写锁定的”。(很抱歉,我最初的印象是不正确的,一个单例EJB的默认锁是“读”锁和“写”锁,这样,更改状态的方法应该默认为“写”锁,其余的,如果有的话,不更改状态的应该默认为“读”锁)。@Tiny:the
@Lock(read)
确实是一个误导性的名称,因为它基本上意味着该方法变得不同步,而不是同步(即调用该方法时没有任何内部锁)。但是,当调用
@Lock(WRITE)
方法时,整个实例将被锁定,包括对
@Lock(READ)
方法的所有访问。