论坛首页 Java企业应用论坛

Spring的事务管理难点剖析(4):多线程的困惑

浏览 19596 次
该帖已经被评为精华帖
作者 正文
   发表时间:2012-03-13  
按照文中的传统dao来说 一个dao可以调用另一个dao吗?
0 请登录后投票
   发表时间:2012-03-14  
这和事务的传播方式有关系吧
0 请登录后投票
   发表时间:2012-03-14  
lilifee 写道
qq123zhz 写道
跨线程的事务,估计要把线程做成阻塞式的。。。


具体要怎么弄呢,能否给出一个实例?

你可以利用一下jdk5.0的blockArray,在线程中使用阻塞队列,对线程进行阻塞,不过这样估计所有的线程都不是并发的了。
0 请登录后投票
   发表时间:2012-03-14  
suixinsuoyu12519 写道
请问能解释下文中提到的有状态和无状态的意思吗?

spring本质上讲是无状态的,里面提到的单例模式,是容器只存在一个共享的bean实例,他其实更适合于无状态的情景,
否则你得自己考虑线程问题。
可以参考ejb3,seam框架里面提到的有状态。
0 请登录后投票
   发表时间:2012-03-14   最后修改:2012-03-14
nighthawk 写道
suixinsuoyu12519 写道
请问能解释下文中提到的有状态和无状态的意思吗?

spring本质上讲是无状态的,里面提到的单例模式,是容器只存在一个共享的bean实例,他其实更适合于无状态的情景,
否则你得自己考虑线程问题。
可以参考ejb3,seam框架里面提到的有状态。

  其实有状态和无状态可以简单归结为:单实例对象在多线程并发的情况下会不会出现问题。如以下类对象:
 public class User{
   private String userName;
   private String password;
}

  这个User类因为持有userName和password这“两个状态”,因此在多线程的环境中,它不是线程安全的,因此我们说它是有状态的,也不能是单实例的,必须每个访问线程new一个实例出来。
  如果是以下的类:
  public class LogonController{

   public String logon(String userName,String passowrd){
     ...
   }
}

   由于LogonController没有成员变量,它的logon()方法内部声明的变量是局部的,因此LogonController是无状态的,也即可以做成单实例的方式,在多线程并发时不会有问题,是线程安全的。
   但是,如果LogonController调整为:
  public class LogonController{
   private String userName;
   private String password;
   public String logon(String userName,String passowrd){
      this.userName = userName;
      this.password = password;
     ...
   }
}

   由于此时,LogonController拥有userName和password的成员变量,多线程并发时就会存在并发问题,因此就有状态了,此时必须每个请求线程new一个LogonController实例出来,以防止并发问题。
   但是,这并不能说,有成员变量的就是有状态了,无成员变量就是有状态了。如果我们要让带成员变量的LogonController无状态,一个常用的方法就是使用ThreadLocal,如下所示:
  public class LogonController{
   private ThreadLocal<String> userName = new ThreadLocal<String>();
   private ThreadLocal<String> password = new ThreadLocal<String>();
   public String logon(String userName,String passowrd){
      this.userName.set(userName);
      this.password.set(password);
     ...
   }

   private String getUppercaseUserName(){
      return  this.userName.get().toUppercase(); 
   }
}

   我们将userName成员变量保存到ThreadLocal中,这样每个线程都得到一个自己线程的一个拷贝,不会访问到其它线程的userName,原来线程相关的userName就线程无关了,因此,我们就可以说经过如上改造的LogonController是无状态了,相应的,这时的LogonController又可以声明为单例了。
    ThreadLocal是深刻了解Spring技术内幕所必须事先掌握的基础Java知识,关于ThreadLocal,在我的《Spring 3.x企业应用开发实战》中有更深入的分析。
0 请登录后投票
   发表时间:2012-03-14  
stamen 写道
nighthawk 写道
suixinsuoyu12519 写道
请问能解释下文中提到的有状态和无状态的意思吗?

spring本质上讲是无状态的,里面提到的单例模式,是容器只存在一个共享的bean实例,他其实更适合于无状态的情景,
否则你得自己考虑线程问题。
可以参考ejb3,seam框架里面提到的有状态。

  其实有状态和无状态可以简单归结为:单实例对象在多线程并发的情况下会不会出现问题。如以下类对象:
 public class User{
   private String userName;
   private String password;
}

  这个User类因为持有userName和password这“两个状态”,因此在多线程的环境中,它不是线程安全的,因此我们说它是有状态的,也不能是单实例的,必须每个访问线程new一个实例出来。
  如果是以下的类:
  public class LogonController{

   public String logon(String userName,String passowrd){
     ...
   }
}

   由于LogonController没有成员变量,它的logon()方法内部声明的变量是局部的,因此LogonController是无状态的,也即可以做成单实例的方式,在多线程并发时不会有问题,是线程安全的。
   但是,如果LogonController调整为:
  public class LogonController{
   private String userName;
   private String password;
   public String logon(String userName,String passowrd){
      this.userName = userName;
      this.password = password;
     ...
   }
}

   由于此时,LogonController拥有userName和password的成员变量,多线程并发时就会存在并发问题,因此就有状态了,此时必须每个请求线程new一个LogonController实例出来,以防止并发问题。
   但是,这并不能说,有成员变量的就是有状态了,无成员变量就是有状态了。如果我们要让带成员变量的LogonController无状态,一个常用的方法就是使用ThreadLocal,如下所示:
  public class LogonController{
   private ThreadLocal<String> userName = new ThreadLocal<String>();
   private ThreadLocal<String> password = new ThreadLocal<String>();
   public String logon(String userName,String passowrd){
      this.userName.set(userName);
      this.password.set(password);
     ...
   }

   private String getUppercaseUserName(){
      return  this.userName.get().toUppercase(); 
   }
}

   我们将userName成员变量保存到ThreadLocal中,这样每个线程都得到一个自己线程的一个拷贝,不会访问到其它线程的userName,原来线程相关的userName就线程无关了,因此,我们就可以说经过如上改造的LogonController是无状态了,相应的,这时的LogonController又可以声明为单例了。
    ThreadLocal是深刻了解Spring技术内幕所必须事先掌握的基础Java知识,关于ThreadLocal,在我的《Spring 3.x企业应用开发实战》中有更深入的分析。

谢谢你LZ了,呵呵理解了!
0 请登录后投票
   发表时间:2012-03-16  
我看还是很少需要跨线程同事务的需求吧,反正我是想不到这样的需求。
0 请登录后投票
   发表时间:2012-03-16  
  除了ThreadLocal外,还可以通过synchronize来同步线程防止线程安全吧?这两个之间有什么优劣势呢?
0 请登录后投票
   发表时间:2012-03-16  
分析得很深刻啊!!
0 请登录后投票
   发表时间:2012-03-16  
nighthawk 写道
suixinsuoyu12519 写道
请问能解释下文中提到的有状态和无状态的意思吗?

spring本质上讲是无状态的,里面提到的单例模式,是容器只存在一个共享的bean实例,他其实更适合于无状态的情景,
否则你得自己考虑线程问题。
可以参考ejb3,seam框架里面提到的有状态。

   Spring本质上是无状态的?应该是默认情况下吧,也可以配置成prototype啊!
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics