Java 无状态会话bean中的多线程?

Java 无状态会话bean中的多线程?,java,multithreading,jakarta-ee,ejb-3.0,ejb,Java,Multithreading,Jakarta Ee,Ejb 3.0,Ejb,EJB3.0规范不允许无状态会话bean的业务方法创建新线程。为什么呢?创建只进行原始计算而从不调用应用服务器的额外工作线程有什么错 比如说,我的会话bean实现了一个允许用户上传图像的服务,业务方法对这些图像进行cpu密集型的图像处理。那么,即使机器有8个或更多内核,它也只能使用一个cpu内核来完成这项工作?如果我使用第三方图像处理库,该库在内部创建工作线程,我也会违反EJB规范,即使该库和这些线程与EJB容器没有任何关系。这似乎不对 如果我忽略EJB规则,仍然创建一些工作线程来进行cpu密集

EJB3.0规范不允许无状态会话bean的业务方法创建新线程。为什么呢?创建只进行原始计算而从不调用应用服务器的额外工作线程有什么错

比如说,我的会话bean实现了一个允许用户上传图像的服务,业务方法对这些图像进行cpu密集型的图像处理。那么,即使机器有8个或更多内核,它也只能使用一个cpu内核来完成这项工作?如果我使用第三方图像处理库,该库在内部创建工作线程,我也会违反EJB规范,即使该库和这些线程与EJB容器没有任何关系。这似乎不对

如果我忽略EJB规则,仍然创建一些工作线程来进行cpu密集型处理,会发生什么?当然,这些线程永远不会接触任何appserver对象,bean线程将在返回之前加入它们。还会有不好的事情发生吗

EJB3.0规范不允许无状态会话bean的业务方法创建新线程。为什么呢

简短版本:不允许从EJB管理线程,因为这会损害资源管理、事务管理和安全性(技术原因),也因为这是EJB模型不希望推广的东西(哲学原因)

EJB规范是这样描述的:

21.1.2编程限制

  • 企业bean不能试图管理线程。企业bean不能尝试启动、停止、挂起或恢复线程,也不能更改线程的优先级或名称。企业bean不能试图管理线程组
这些函数是为EJB容器保留的。允许企业bean管理线程会降低容器正确管理运行时环境的能力

另见
    • 第2.1节“容器托管线程与非托管线程”
(…)如果我使用第三方图像处理库,在内部创建工作线程,我也会违反EJB规范,即使该库和这些线程与EJB容器没有任何关系。这似乎不对

我能说什么呢?如果你不喜欢,就不要使用EJB

如果我忽略EJB规则,仍然创建一些工作线程来进行cpu密集型处理,会发生什么?当然,这些线程永远不会接触任何appserver对象,bean线程将在返回之前加入它们。还会有不好的事情发生吗

这些线程是否接触应用服务器对象并不重要。规则就是规则,你不想遵守它们,你只能靠自己,行为是不确定的。有些容器可能更为宽松,允许使用它,有些容器则不允许,您的应用程序将不可移植,等等。但它仍然被明确禁止

如果希望以标准方式“生成”线程,请使用WorkManager API或JMS

相关问题

这是已知的限制,不允许在J2EE应用程序中使用线程。 应用服务器应该负责程序的并行执行


是的,您可以忽略EJB规则,但可以面对极其不可预测的行为。在我的简单理解中,这就像经营一家公司。你是老板(容器),有一个员工突然突然在没有任何通知的情况下雇佣了100人(豆子)

但您仍然可以轻松地使用@Asynchronous注释进行多线程处理(还有其他方法)

@无状态
公营雇员{
@异步的
公共未来工作(需要很长时间的项目){
//工作
返回新的异步结果(空);
}
}
@无国籍
公务舱老板{
@注入
私人雇员;
公共工程(){
Future result1=randomstationemployee.work(新项目());
Future result2=randomstationemployee.work(新项目());
Future result3=randomstationemployee.work(新项目());
结果1.get();
结果2.get();
结果3.get();
}
}
这里还有一个更好的例子:
一种解决方法:

import java.util.concurrent.Executor;
import javax.ejb.Asynchronous;
import javax.ejb.Stateless;

@Stateless
public class TransactionalExecutor implements Executor {

    @Override @Asynchronous
    public void execute(Runnable command) {
        command.run();
    }
}
现在您可以使用TransactionalExecutor作为执行者:

@Stateless
public class SlowService {

    @Inject
    Executor command;

    public void invoke(){
        Runnable command = new Runnable() {
            @Override
            public void run() {
                // heavy task
            }
        };
        command.execute(command);
    }    
}
@Stateless
public class SlowService {

    @Inject
    Executor command;

    public void invoke(){
        Runnable command = new Runnable() {
            @Override
            public void run() {
                // heavy task
            }
        };
        command.execute(command);
    }    
}