纳入spring容器管理的类是线程安全的么?

coolbamboo2008 2009-08-17 06:28:27
就是在beans.xml中定义的,比如<bean id="admindao" class="DAO.impl.AdminDaoImpl"></bean>这个类DAO.impl.AdminDaoImpl,我调用时是线程安全的吗?

再有,整合struts和spring时,可以把struts的action纳入spring容器管理,比如<bean name="/logindeal" class="action.Logindeal"></bean>,这里的/logindeal是个action。因为action是线程不安全的,那么我想知道这样纳入spring容器后是不是就线程安全了?

如果以上都是线程不安全的,那么怎么做(尤其是整合struts和spring的)能保证线程安全?
...全文
866 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
radeonxhl 2009-08-17
  • 打赏
  • 举报
回复
同意10楼的

1.首先楼主要理解为什么会产生线程不安全的情况,然后再去考虑一个类是否线程安全
2.其次,线程是否安全,其实和spring、struts没有必然关系
你说struts的action不是线程安全的,那是因为你在action里定义了属性
比如:

public class SampleAction extends Action {
private String user = null;
...
}

如果有多个用户上来访问这个SampleAction,而且每个用户都要来修改user属性或者说是要对user进行某种操作,那么这就是一种线程不安全的情况,或者说是场景。
但是,如果你不定义这个user属性,也不定义任何其他属性,那么这个SampleAction就不存在线程不安全的问题。还有种情况,如果你这个属性定义成final的,只是在初始化的时候进行一次赋值,以后所有的操作都只是读取、而不会修改这个属性的值,那么也不会有线程安全的问题。

再比如,有一个类User,你每次使用这个类的时候都是new出来的,那么这个类一定是线程安全的吗?也不一定。

public class User {
private static String name = null;

public User(String name) {
User.name = name;
}
}

对于这个User类,即使你每次都是new一个新的,它也不是线程安全的。
Landor2004 2009-08-17
  • 打赏
  • 举报
回复
1 struts1的action是单例的,所以存在线程安全问题
2 spring默认的注入也是单例的,所以也存在线程安全问题

先理解为何会有线程不安全的问题,比如有一个类Person 有个属性是name,线程1修改了这个属性的name,要进行存入数据库操作的时候,线程2又修改了这个name,这样线程1就存入了一个线程2修改过的数据了。

避免的方法很简单
struts1如果被spring管理,那么可以设置成scope为protype,这样action就不是单例了,而是为每个线程都创建一个;
线程安全是可以避免的,就是禁止用可变动的成员变量,如果都是局部变量的话,即使是单例的也不存在任何问题

private JdbcTemplate jdbcTemplate;
private LobHandler lobHandler;
里面没什么可变成员变量,说以他们是单例的,但是不会有线程问题
阿士匹灵 2009-08-17
  • 打赏
  • 举报
回复
帮顶
Johnson_Hong 2009-08-17
  • 打赏
  • 举报
回复
假设你的
dao里有一个private Session s,那么你如果用spring默认的singlton来配置dao就会出问题,像Session这样的非线程安全的变量,不同的线程程是不能共享的

如果dao的变量是private SessionFactory sf,或者hibernateTemplate,这样允许共享的只读变量
那么dao就可以配置成singlton
-------------------
最常见的实例是struts2的action,因为action的成员变量要保存表单的输入值,如果struts2的action配置成单例,那么不同的请求就会相互覆盖action的属性值,出现线程安全问题,所以对于持有有状态属性的bean,一般配置成protocol

而对于struts1,他的action里一般没有有状态的属性,所以配置成单例或者protocol都可以
blliy117 2009-08-17
  • 打赏
  • 举报
回复
如果是单例模式的,那最好不要在action中设置属性(类似无状态的),只要方法就可以
这样的话就不会存在比较安全问题了。

即使多线程一起调用也没关系


好吃的松子 2009-08-17
  • 打赏
  • 举报
回复
不会有问题
coolbamboo2008 2009-08-17
  • 打赏
  • 举报
回复
还有,JdbcTemplate和LobHandler是线程安全的么?比如这样写是否线程安全:
public class PersonServiceBean implements PersonService {

private JdbcTemplate jdbcTemplate;
private LobHandler lobHandler;

public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}

public void delete(int personid) throws Exception {
jdbcTemplate.update(.....);
}
}
好吃的松子 2009-08-17
  • 打赏
  • 举报
回复
我是二楼的
刚查了下spring的书,spring默认是单例模式,但它会对非线程安全的变量进行特殊处理,也就是利用AOP和LocalThread类进行转变,使其成为线程安全的类。
coolbamboo2008 2009-08-17
  • 打赏
  • 举报
回复
我是楼主,问题是这样的,整合了struts和spring后,我现在的action里面有属性,属性是依赖注入的。
比如:
public class deal extends Action {

@Resource
AdminDao admindao;

public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {

admindao.getXXXX();
......
}
}
我在beans.xml里面定义接口admindao的实例,然后依赖注入,用到注解。
我想知道,这样的话会不会线程不安全?AdminDao admindao这样定义的变量在struts中是线程不安全的,那么现在呢?
好吃的松子 2009-08-17
  • 打赏
  • 举报
回复
也没必要偏要spring是线程安全的,你写的action是线程安全就行了

spring好像默认是线程安全的,有个singlton属性配置吧
jaunty_1127 2009-08-17
  • 打赏
  • 举报
回复
关于楼主的疑问不如看看TreadLocal的源代码,就了解了。
其实就是一个大Map,里面用Thread id作为key,存Object。
这样对于非线程安全的hibernate session、transaction status等通过treadlocal保存就可以保证每个线程都有独立的这些object实例了,也就不存在线程安全问题了。只有那些有状态的单例组件才存在线程安全问题 什么是有状态的组件:存在可变的实例变量 所以,如果你的spring pojo只是有一些像datasource或者sessionfactory这样的不变的实例变量,那么即使它是单例也不用担心线程安全问题
以前有人解释过,TreadLoacl的想法就是把资源私有化的容器。以此类推其它方案。

67,512

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧