将服务层传递给线程的正确方法

时间:2009-12-14 03:04:17

标签: java spring multithreading

我的服务层方法是事务性的,当我使用ExecutorService并将任务提交给线程时,我无法将servicelayer作为参数传递给每个线程,因为我收到错误

Dec 14, 2009 10:40:18 AM com.companyx.applicationtest.applicationtestcompanyx.services.threadtestRunnable run
SEVERE: null
org.hibernate.HibernateException: No Hibernate Session bound to thread, and conf
iguration does not allow creation of non-transactional one here
        at org.springframework.orm.hibernate3.SpringSessionContext.currentSessio
n(SpringSessionContext.java:63)
        at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactor
yImpl.java:542)

我的服务层

ExecutorService executor = Executors.newFixedThreadPool(10);
                  for (final Object item : CollectionsTest{ 
                      executor.submit(new threadtestRunnable((Long)item,collectionAfterfiltered,this));  //'this' is service layer
                  }
  1. 我应该将服务层传递给这样的每个线程吗?
  2. 什么是正确的方法,我需要每个线程在服务层调用方法? (我正在使用春天)

1 个答案:

答案 0 :(得分:3)

通常,如评论中所述,不应在多个线程中运行事务。但是,有些情况可以接受。

  • 您需要与Web服务进行一些异步通信(不要让用户等待结果),并在结果出来时存储结果
  • 您需要多个线程中的只读事务。

如果使用new创建线程,则它不属于spring上下文。因此,当创建线程的方法完成时,您的事务拦截器将关闭事务(和最终的会话),并且您将获得上述异常。

(有关详细信息 - Spring docs,请参阅“查找注入”)

您需要在spring上下文中创建线程。由于您可能正在从singleton bean创建它们,因此从prototype bean创建singleton bean的情况很少见。因此,为了在spring上下文中创建一个线程,您可以使用:

 <bean id="mainBean"
    class="com.my.MyClass">
    <lookup-method name="createThread" bean="myThreadBean"/>
 </bean>

您还应该将ThreadtestRunnable课程映射到applicationContext.xml或将其注释为@Component("myThreadBean")

然后在名为abstract的主bean上定义createThread方法并返回您的线程类。使用@Transactional注释您的run方法(或定义相应的aop规则),然后尝试一下。也许您需要在propagation=Propagation.REQUIRES_NEW"中设置@Transactional。如果有任何问题,请回到这里。