您现在的位置:首页 > 教案格式 > 正文

变量之间的相关关系 (转载)有关线程安全的探讨--final、static、单例、线程安全(2)

2017-12-22 17:04 网络整理 教案网

于是,就很容易想到,将 SimpleDateFormat定义为静态类变量,貌似能解决这个问题

于是这就引出了,SimpleDateFormat是非线程安全的,这样的使用方式可能引发并发线程安全问题

SimpleDateFormat类内部有一个Calendar对象引用,它用来储存和这个SimpleDateFormat对象(叫sdf)相关的日期信息,例如sdf.parse(dateStr), sdf.format(date)

诸如此类的方法参数传入的日期相关String, Date等等, 都是交友Calendar引用来储存的

这样就会导致一个问题:如果你的sdf是个static的, 那么多个thread 之间就会共享这个sdf, 同时也是共享这个Calendar引用, 并且, 观察 sdf.parse() 方法,你会发现有如下的调用:

Date parse() {

?? calendar.clear(); // 清理calendar

?? ... // 执行一些操作, 设置 calendar 的日期什么的

?? calendar.getTime(); // 获取calendar的时间

}

这里会导致的问题就是:如果 线程A 调用了 sdf.parse(), 并且进行了 calendar.clear()后还未执行calendar.getTime()的时候,线程B又调用了sdf.parse(), 这时候线程B也执行了sdf.clear()方法, 这样就导致线程A的的calendar数据被清空了(实际上A,B的同时被清空了). 又或者当 A 执行了calendar.clear() 后被挂起, 这时候B 开始调用sdf.parse()并顺利i结束, 这样 A 的 calendar内存储的的date 变成了后来B设置的calendar的date

上边是复杂的具体的原因,而这个原因简单说就是,在线程中调用了一个static对象,这个对象存储值的变量被多个线程同时使用(修改),造成了混乱

你肯定是喜欢使用匿名内部类的,以这个为基础

注意如果是调用所在方法中的局部变量,尽量不要绕过final机制,如果需要绕过,而且会对这个局部变量进行修改的话,那一定是知道不会多个这样的线程同时运行(比如作为UI主线程外的一个子线程,这个子线程只会有一个)

不要尝试修改不是在自己内部实例化出的对象的值(只能改局部变量的值)(尽量使用局部变量)

你还喜欢使用静态工具方法,所有的静态工具方法中使用变量尽量使用局部变量(for循环中的i++ 是没有问题的),尽量少地使用静态变量,更不要尝试对静态变量的值进行修改