例如:
static private DateFormat df = new SimpleDateFormat();
public static void format(final Date date) {
for (int i = 0; i < 10; i++)
new Thread(new Runnable() {
public void run() {
System.out.println(df.format(date));
}
});
}
The DateFormat
类被记录为不是同步类,但是如果我们只使用 format 方法,它不能改变整个类的状态?
假设它被声明为私有,如何确定代码是线程安全的?
修复此代码的最佳方法是什么?:
为每个线程使用不同的实例。
使用同步块。
- 对于标准的 Java SE 类,了解该类是否线程安全的最佳方法是仔细阅读其文档。请务必阅读类文档和方法文档。如果说它不是同步的或不是线程安全的,那么您就知道它不是线程安全的。
-
因此,DateFormat
类是not线程安全。文档具体说:
日期格式不同步。建议为每个线程创建单独的格式实例。如果多个线程同时访问某种格式,则必须进行外部同步。
-
声明一个字段private
does not使您的实现线程安全。private
只是说外部类看不到该字段。让我们看看你的方法:
for (int i=0;i<10;i++)
new Thread(new Runnable(){
public void run(){
System.out.println(df.format(date));
}
});
The Runnable
您创建的对象是匿名类。匿名类是inner类,可以访问其周围类的私有字段。如果不是这样,你的程序将无法编译 - 他们无法访问df
field.
但他们可以。所以事实上你有 10 个线程都在访问你的线程DateFormat
对象,由df
。既然我们已经知道DateFormat
is not线程安全,你的程序不是线程安全的。
- 此外,如果两个外部线程引用了您的对象(我的意思是具有
df
在里面。您没有给出类声明,所以我不知道它的名字是什么)。它们引用了您的类的同一实例。如果他们两个都打电话format
同时,两者都将运行DateFormat.format
使用相同的私有df
。因此,这不会是线程安全的。
- 为了实现线程安全,您需要在对象上进行同步或使用某种其他类型的锁(对所有可能访问该对象的线程使用一个锁),这正是文档所说的要做的事情。
- 另一种方法是拥有一个完全本地的对象,该对象仅对一个线程可见。不是字段 - 局部变量,可以访问唯一创建的实例
DateFormat
(因此每次调用该方法时都会有一个新副本)。但要小心匿名类!在你的例子中,即使df
是当地的一个领域format
方法,它仍然不是线程安全的,因为所有线程都将访问相同的副本。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)