java 无状态会话 bean 中的多线程?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3816286/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Multithreading in a stateless session bean?
提问by Gerald Thaler
The EJB 3.0 specification does not allow a business method of a stateless session bean to create new threads. Why is that? What is wrong with creating additional worker threads that only do raw computations and never call into the app server?
EJB 3.0 规范不允许无状态会话 bean 的业务方法创建新线程。这是为什么?创建仅执行原始计算且从不调用应用服务器的额外工作线程有什么问题?
Say, my session bean implements a service that lets users to upload images, and the business method does cpu-intensive image processing on these images. Then it can only use one cpu core to do this job, even if the machine has 8 or more cores? If i utilize a third party image processing library, that internally creates worker threads, i would also violate the EJB specs, even though that library and these threads have nothing to do with the EJB container at all. This does not seem right.
比如说,我的session bean实现了一个让用户上传图片的服务,业务方法对这些图片做cpu密集的图片处理。那么它只能使用一个cpu核心来完成这项工作,即使机器有8个或更多核心?如果我使用在内部创建工作线程的第三方图像处理库,我也会违反 EJB 规范,即使该库和这些线程与 EJB 容器完全无关。这似乎不对。
What can happen if i ignore the EJB rules and still create some worker threads to do cpu intensive processing? Of course these threads will never touch any app server objects and the bean thread will join them before returning. Can still something bad happen?
如果我忽略 EJB 规则并仍然创建一些工作线程来执行 cpu 密集处理会发生什么?当然,这些线程永远不会接触任何应用程序服务器对象,并且 bean 线程将在返回之前加入它们。还会有不好的事情发生吗?
回答by Pascal Thivent
The EJB 3.0 specification does not allow a business method of a stateless session bean to create new threads. Why is that?
EJB 3.0 规范不允许无状态会话 bean 的业务方法创建新线程。这是为什么?
Short version: managing threads from EJBs is disallowed because it would harm resource management, transaction management, security (technical reasons) and also because this is something the EJB model doesn't want to promote (philosophical reason).
简短版本:不允许从 EJB 管理线程,因为它会损害资源管理、事务管理、安全性(技术原因),也因为这是 EJB 模型不想推广的东西(哲学原因)。
The EJB specification puts it like this:
EJB 规范是这样写的:
21.1.2 Programming Restrictions
...
- The enterprise bean must not attempt to manage threads. The enterprise bean must not attempt to start, stop, suspend, or resume a thread, or to change a thread's priority or name. The enterprise bean must not attempt to manage thread groups.
These functions are reserved for the EJB container. Allowing the enterprise bean to manage threads would decrease the container's ability to properly manage the runtime environment.
21.1.2 编程限制
...
- 企业 bean 不得尝试管理线程。企业 bean 不得尝试启动、停止、挂起或恢复线程,或者更改线程的优先级或名称。企业 bean 不得尝试管理线程组。
这些功能是为 EJB 容器保留的。允许企业 bean 管理线程会降低容器正确管理运行时环境的能力。
See also
也可以看看
- Why is thread creation and management disallowed?in the EJB Restrictions FAQ
- Why are beans not allowed to create their own threads?
- Concurrency Utilities for Java EE
- Section 2.1 "Container-Managed vs. Unmanaged Threads"
- 为什么不允许创建和管理线程?在EJB 限制常见问题解答中
- 为什么 bean 不允许创建自己的线程?
- Java EE 的并发实用程序
- 第 2.1 节“容器管理与非托管线程”
(...) If i utilize a third party image processing library, that internally creates worker threads, i would also violate the EJB specs, even though that library and these threads have nothing to do with the EJB container at all. This does not seem right.
(...) 如果我使用在内部创建工作线程的第三方图像处理库,我也会违反 EJB 规范,即使该库和这些线程与 EJB 容器根本没有任何关系。这似乎不对。
What can I say, don't use EJBs if you don't like this.
我能说什么,如果您不喜欢这个,请不要使用 EJB。
What can happen if i ignore the EJB rules and still create some worker threads to do cpu intensive processing? Of course these threads will never touch any app server objects and the bean thread will join them before returning. Can still something bad happen?
如果我忽略 EJB 规则并仍然创建一些工作线程来执行 cpu 密集处理会发生什么?当然,这些线程永远不会接触任何应用程序服务器对象,并且 bean 线程将在返回之前加入它们。还会有不好的事情发生吗?
Whether these threads are touching the app server objects or not doesn't matter. Rules are rules, you don't want to follow them, you're on your own and the behavior is undefined. Some container might be more permissive and allow it, some other won't, your application won't be portable, etc. But it's still explicitly forbidden.
这些线程是否接触应用服务器对象并不重要。规则就是规则,你不想遵循它们,你是靠自己的,行为是不确定的。一些容器可能更宽容并允许它,其他一些则不会,您的应用程序将不可移植等。但它仍然被明确禁止。
If you want to "spawn" threads in a standard way, use the WorkManager API, or use JMS.
如果您想以标准方式“生成”线程,请使用 WorkManager API,或使用 JMS。
Related Questions
相关问题
回答by Rowanto
In my simplified understanding, it's like running a company. You're the boss (the container), and there's an employee which suddenly just hire 100 people out of the blue without any notice (the bean).
在我的简单理解中,这就像经营一家公司。你是老板(容器),有一个员工突然在没有任何通知的情况下雇佣了 100 人(豆子)。
But you can still easily do multithreading with the @Asynchronous annotation (there are other ways too).
但是您仍然可以使用@Asynchronous 注释轻松地进行多线程处理(还有其他方法)。
@Stateless
public class Employee {
@Asynchronous
public Future<Void> work(Project projectThatTakeTooLong) {
// work work work
return new AsyncResult<Void>(null);
}
}
@Stateless
public class Boss {
@Inject
private Employee randomStatelessEmployee;
public void giveWork() {
Future<Void> result1 = randomStatelessEmployee.work(new Project());
Future<Void> result2 = randomStatelessEmployee.work(new Project());
Future<Void> result3 = randomStatelessEmployee.work(new Project());
result1.get();
result2.get();
result3.get();
}
}
There's also a better example here: Jboss Java EE container and an ExecutorService
这里还有一个更好的例子: Jboss Java EE container and an ExecutorService
回答by Orbita
One type of workaround:
一种解决方法:
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();
}
}
Now you can use TransactionalExecutor as an executor:
现在你可以使用 TransactionalExecutor 作为执行器:
@Stateless
public class SlowService {
@Inject
Executor command;
public void invoke(){
Runnable command = new Runnable() {
@Override
public void run() {
// heavy task
}
};
command.execute(command);
}
}
回答by Andriy Sholokh
This is known restriction not to use threads in J2EE applications. Application server should take care of parallel execution of the program
这是在 J2EE 应用程序中不使用线程的已知限制。应用服务器应该负责程序的并行执行
Yes, you can ignore the EJB rules but can face with extremely unpredictable behaviour.
是的,您可以忽略 EJB 规则,但可能会面临极其不可预测的行为。