我可以在无限线程中使用 EJB 吗?

Can I use an EJB in an infinite thread

我想知道是否禁止在无限线程中使用 EJB(因为它不能返回给容器)。

像这样:

@ManagedBean(eager = true)
@ApplicationScoped
public class TestListenner {

    private ResultThread result;

    @PostConstruct
    public void init() {
        result = new ResultThread ();
        Thread myThread = new Thread(result);
        myThread.start();
    }
    public ResultThread getResult() {
        return result;
    }
}

和线程:

public class ResultThread implements Runnable{
    @EJB
    private SomeService service;
    private boolean continueWork = true;

    public void run(){
        while(continueWork){
            service.doSomething();
            //some proccessing
        }
    }

自从我开始使用数据库以来,我就在使用 EJB。我浏览了 daofactories 之类的东西,但我忘记了它们(那是一年前)。当用户在我的网络应用程序上请求网页时,我使用它们对我的数据库执行操作。但是现在我需要一个线程来连续计算数据库中的内容以减少响应时间。如果由于容器需要处理它们而无法使用 EJB,那么我应该使用什么?

希望我可以使用类似于我过去使用的 class:

@Stateless
public class SomeServiceImpl implements SomeService {
    @PersistenceContext(unitName = "my-pu")
    private EntityManager em;

    @Override
    public void updateCategory(SomeClass theclass) {
        em.merge(theclass);
    }
}

编辑:本主题中的 The first answer by BalusC 似乎暗示在无法生成其他线程的情况下,在 ManagedBean 中生成线程不会有危险。由于我的 bean 是 ApplicationScoped,Web 应用程序使用 1 个且仅使用它的 1 个实例在数据库上进行后台工作(我实际上喜欢 TOP 100 "posts" table 需要不断随着时间的推移重新计算,所以我可以查询 table - 使用另一个 bean - 以获得快速答案)。

至少有一个原因使您现在拥有的功能不起作用:

You can't inject resources into non-managed components。要使 @EJB 注释起作用,ResultThread 应该是一个托管 bean,并由容器注入。这意味着,您至少必须使用 CDI 来注入它,而不是您现在拥有的 new ResultThread。什么会起作用看起来像:

@Inject
private ResultThread result;

这样,容器就会参与进来。

然而,最重要的是,有更好的方法可以完成您似乎正在尝试做的事情。

您可能还想知道不允许 EJB 产生自己的线程;事实上,在容器中进行任何手工穿线是不受欢迎的。为什么?容器是一个托管环境——其中的内存和并发性已经经过深思熟虑和设计。您的手工线程破坏了该模型以及容器可能已经能够为您提供 bean 和其他应用程序组件的任何保证

相关:

  • Why is spawning threads in Java EE container discouraged?

您不能在 Java EE 容器上使用自己的线程。

http://www.oracle.com/technetwork/java/restrictions-142267.html#threads

Java EE 规范为此类工作提供了 TimerServices。

https://docs.oracle.com/javaee/6/tutorial/doc/bnboy.html