我有一个使用spring和hibernate以及struts的Web应用程序(它在Tomcat上运行)
呼叫序列是这样的......
Struts动作调用spring服务bean,后者又调用Spring DAO bean。 DAO实现是一个Hibernate实现。
问题是 我的所有春豆都会在同一个线程中运行吗? 我可以在ThreadLocal中存储一些内容并将其放入另一个bean中吗?
我很确定这在无状态会话Bean中不起作用。 EJB容器可以(或将)为每次调用会话bean
生成一个新线程弹簧容器会不会这样做?即在同一个线程中运行所有bean?
当我尝试JUnit测试时 - 我通过测试用例中的Thread.currentThread()。getId()和两个bean得到相同的id - 这让我相信只有一个线程在运行
或者这种行为是不可预测的? 或者在Tomcat服务器上运行时会改变吗?
澄清 我不希望在两个线程之间交换数据。我想将数据放在ThreadLocal中,并能够从调用堆栈中的所有bean中检索它。只有当所有bean都在同一个线程
时,这才有效答案 0 :(得分:15)
Spring不会产生线程。 Tomcat呢。 Spring只是为你创建和连接对象。
浏览器的每个请求都在一个请求中处理。是Tomcat处理请求。 Tomcat创建了处理请求的线程。
假设您刚刚在Spring中创建了一个名为“X”的单例bean。然后,所有请求都使用相同的X实例。
Spring bean不存在于一个线程中。它们只是在堆上分配。
答案 1 :(得分:1)
我所有的春豆都会跑 在同一个线程?我可以存储吗? 在ThreadLocal中得到的东西 它在另一个豆? AFAIK为您提到的组件(服务bean,DAO bean - 我猜它们是普通的spring bean),Spring不会产生新的线程。我不明白你的用例(即在两个线程之间交换数据)。
对于大多数webapps,会为每个新请求生成一个新线程,如果要在两个请求之间共享数据,通常是: - 使用get / post参数传递数据 - 使用会话共享数据
要回答你的问题,我很确定spring容器不会为大多数组件生成线程。
答案 2 :(得分:0)
是的,你可以这样做。将使用相同的线程来执行您的操作,以便ThreadLocal可以工作。通常,相同的线程也用于无状态会话bean,假设它在同一个应用服务器实例中运行。我不会依赖于此,因为它可能依赖于供应商。
我们使用此技术在代码中的任何位置访问调用者身份。我们也使用会话bean和jms,但是在容器之间显式传递信息并在每个入口点设置ThreadLocal。这样,bean(session或mdb)是否是本地的并不重要。
答案 3 :(得分:0)
除了所有其他答案之外,我将添加以下内容:
通常,切换线程的唯一原因是因为对并行性有一些要求。由于这通常不会在复杂性方面免费提供,因此通常会在发生这种情况时通知您。
在似乎是请求的单线程处理的情况下切换线程实际上非常复杂。这通常只发生在容器中的一个地方,这通常由接收外部客户端请求的tcp / ip套接字读取器处理。这些读取器线程通常确定哪个线程(池)应该处理请求并将请求转发给该线程。之后,请求将保留在该线程中。
通常,唯一能够/可能发生的事情是为并行或异步处理(如JMS)创建额外的线程。