seam中使用多线程的问题

08-11-25 940609296
         

我用的seam架构的项目,目前想在系统中让服务器启动后就自动启动一个多线程的任务。

我现在用的seam组件类A的一个方法去循环实例化多个继承自Thread的线程类B,而线程类中的run方法又调用了A的一些数据保存方法。所以我在B中实例化了A类,我试了三种方式,

1:以new 关键字实例化

2:Component.getInstance("XXX",true);

3:@In(value="XXX",create=true)

第二种和第三种方式我运行就报空指针,类没有被实例化。而以第一种方式实例化后,A类所牵涉的seam组件类中的数据库操作有时候会报错,有时候又不会。我估计是seam的事务被打乱的原因,报了很多奇怪的错,比如我query.getResultList()的时候,报连接已经关闭,而另外的类里有时会报得到的List是空。而对于我用线程查询出来的集合我把操作集合方法注释后报could not read column value from result set: BATCHS; ORA-01001: 无效的游标。而程序偶尔跑得很正常,该更新的更新,该删除的删除。但是大多时候,是在不固定的地方,报操作过程中用的seam组件的引用为空指针。

还请各位高手指点一下

         

banq
2008-11-26 09:41

总体来说,你启动线程方式有问题。你可以使用JDK5中Executor框架看看。

从设计上也要解决问题,因为B依赖A,所以,将A中那些被依赖的功能从A中重构出来。

saharabear
2008-11-26 11:14

我个人的认为是,尽量不要在框架或者中间件中启动与中间件或框架有关的线程,毕竟中间件就是要帮我们解决线程问题的。

如果真的需要线程,也许通过在中间件中的调用,启动一个独立的线程比较好,以免影响中间件的线程调度。

所以,我认为Seam中不应该使用与线程密切本着的编程。

arthurln
2008-11-26 19:30

最近也在用seam做项目,起线程应该就是要做异步处理(不论是周期的还是一次性的),文档上说了三种实现方式,根据实现的复杂程度分别为:

1.使用EJB的异步机制

2.整合Quartz

3.使用JMS

具体内容文档上说的比较清楚,下边是文档地址:

http://docs.jboss.com/seam/2.1.1.CR1/reference/en-US/html/jms.html

如果希望在系统启动的时候开始处理,可以把调用写到启动的Observer方法中。这里有个不错的例子:http://relation.to/2640.lace

940609296
2008-11-27 21:42

首先 谢谢 各位的指点。

arthurln的方法是对的,现在正是通过@Asynchronous注解方法来调用线程的。不过这种方式组件的实例化就全改成了@In(value="XXX",create=true)这种方式。

现在每个线程调用的是一个有@Transactional注解的方法。

但是在数据库操作的时候,当线程独立没有访问外部变量(比如全局的)的时候不用我操作事务,事务正常提交,而我访问了外部变量后我就必须使用EntityManager的事务手动commit才能提交。这个是什么原因呢?

另外,seam应该有自己的线程池吧,但是我不知道设置最大线程数在什么地方。我现在最多只能启动10个线程。望高手指点一下