JTS和线程的问题,一言难尽,在google里查一查吧

解决方案 »

  1.   

    假设对象 A 的 methodA() 启动一个事务,然后调用对象 B 的 methodB()(对象 B 将得到一个 JDBC 连接并更新数据库)。B 获得的连接将被自动征调到 A 创建的事务中。容器怎么知道要做这件事?当事务启动时,事务上下文与执行线程关联在一起。当 A 创建事务时,A 在其中执行的线程与该事务关联在一起。由于本地方法调用与主调程序(caller)在同一个线程内执行,所以 A 调用的每个方法也都在该事务的上下文中。如果对象 B 其实是在另一个线程,甚至另一个 JVM 中执行的 EJB 组件的存根,情况会怎样?远程对象 B 访问的资源仍将在当前事务中被征用。EJB 对象存根(在主调程序的上下文中执行的那部分)、EJB 协议(IIOP 上的 RMI)和远端的骨架对象协力要使其透明地发生。存根确定调用者是不是正在执行一个事务。如果是,事务标识,或者说 Xid,被作为 IIOP 调用的一部分与方法参数一起传播到远程对象。(IIOP 是 CORBA 远程-调用协议,它为传播执行上下文(比如事务上下文和安全性上下文)的各种元素而备;关于 RMI over IIOP 的更多信息,请参阅参考资料。)如果调用是事务的一部分,那么远程系统上的骨架对象自动设置远程线程的事务上下文,这样,当调用实际的远程方法时,它已经是事务的一部分了。(存根和骨架对象还负责开始和提交容器管理的事务。) 事务可以由任何 J2EE 组件来启动 — 一个 EJB 组件、一个 servlet 或者一个 JSP 页面(如果容器支持的话,还可以是一个应用程序客户机)。这意味着,应用程序可以在请求到达时在 servlet 或者 JSP 页面中启动事务、在 servlet 或者 JSP 页面中执行一些处理、作为页面逻辑的一部分访问多个服务器上的实体 bean 和会话 bean 并使所有这些工作透明地成为一个事务的一部分。
      

  2.   

    [转]说穿了就不会觉得神奇了( 有点像变魔术:-) ),这是由JTA服务器内部实现的,我可以说一下大致的原理(远程事务的部分就不说了(说来话长))。
    当调用begin时,创建一个新事务,并将其放入事务池(是一个Map对象)中,其键值就是线程对象。大概是这样的:TransactionManager.getTranactionPool().put(System.currentThread(),new TransactionObject());
    当事务资源如会话Bean需要用到当前事务对象时,就调用
    TransactionManager.getTranactionPool().get(System.currentThread());来获得。这也就是为什么EJB容器规定不能在容器中启动新线程的原因之一了(因为容器不好控制(也不是不可能)事务在新线程中传播)。
      

  3.   

    [转]
    在JBoss里,你提到的应用是这样实现的:
    首先,你要明确:你用到到的那几个bean位于同一个容器中(跨容器的事务传播JBoss3.x不支持,JBoss4.x我不懂),那么这几个bean的调用将位于同一个线程中。
    而事务管理器TxManager使用了ThreadLocal类型的变量来保存特定线程的事务信息(包括事务对象),这样那几个位于同一线程的调用就共有了同一个事务对象,也就是说被纳入到同一个事务了。就着么简单!因为在取得资源时判断当前是否有事务的方式,就是判断TxManager中的ThreadLocal变量是否保存了事务对象。
    而对于客户端调用EJB方法时的事务传播,因为事务对象其实是存在于容器中的,所以客户端只需在调用EJB方法时顺带捎上事务的全局ID,容器根据改ID取出相应的事务对象,就将客户端和EJB方法纳入到同一个事务中了。这其实是一种变形的跨JVM传播事务,但不是真正的跨JVM传播事务。
      

  4.   

    hutlyx(胡里糊涂) 
    说得不错
      

  5.   

    hutlyx(胡里糊涂) 不错,支持。
      

  6.   

    老兄,你把问题想的太复杂了!事务是一连串操作的集合,没有规定操作必须是一个session发出的啊,把事情分开来看,你的3,4中间的部分不过是一组操做而已,这还有什么问题呢?