如何知道java SE类或方法是否是线程安全的?
例如:
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)); } }); }
它记录的DateFormat类不是同步类,但如果我们只使用格式Method,它不能改变孔类的法定?
假设它被声明为私有,如何确保此代码是线程安全的?
修复此代码的最佳方法是什么?:
1_ Using a different instance for every Thread. 2_ Using a synchronized block.
- 对于标准Java SE类,了解该类是否是线程安全的最佳方法是仔细阅读其文档。 始终阅读课程文档和方法文档。 如果要么说它不同步或不是线程安全的,你知道它不是线程安全的。
-
因此,
DateFormat
类不是线程安全的。 文件具体说:日期格式未同步。 建议为每个线程创建单独的格式实例。 如果多个线程同时访问格式,则必须在外部进行同步。
-
将字段声明为
private
不会使您的实现成为线程安全的。private
只是说外面的课堂看不到那个领域。 我们来看看你的方法:for (int i=0;i<10;i++) new Thread(new Runnable(){ public void run(){ System.out.println(df.format(date)); } });
您创建的
Runnable
对象是匿名类。 匿名类是内部类,可以访问其周围类的私有字段。 如果不是这样,你的程序将无法编译 - 他们无法访问df
字段。但他们可以。 所以实际上你有10个线程都访问你的一个
DateFormat
对象,由df
引用。 由于我们已经知道DateFormat
不是线程安全的,因此您的程序不是线程安全的。 - 此外,如果两个外部线程引用了您的对象(我的意思是在其中包含
df
的对象。您没有给出类声明,因此我不知道它的名称是什么)。 它们引用了同一个类的实例。 如果它们都同时调用format
,则两者都将使用相同的私有df
运行DateFormat.format
。 因此,这不是线程安全的。 - 为了线程安全,您需要在对象上进行同步或使用其他类型的锁(对于访问它的所有可能线程都有一个锁),这正是文档所说的。
- 另一种方法是拥有一个完全本地的对象,只有一个线程可见。 不是字段 - 一个局部变量,它可以访问唯一创建的
DateFormat
实例(因此每次调用该方法时都有一个新副本)。 但要注意匿名课程! 在您的示例中,即使df
是format
方法的本地字段,它仍然不是线程安全的,因为所有线程都将访问同一个副本。
根据文档,声明格式不是线程安全的。
同步
日期格式未同步。 建议为每个线程创建单独的格式实例。 如果多个线程同时访问格式,则必须在外部进行同步。
日期格式
怎么读这个? 如果您没有明确保证某些方法是线程安全的(或者它被记录为不安全),那么您不能对其安全做出任何假设。
但是,如果您真的希望仅使用可能不是statefull的单个方法,则可以始终创建高并发环境并在有和没有同步的情况下测试数据完整性。
我有类似的问题,使用Ciphers和RSA。 答案显示了如何一般地测试java SE类的特定方法的一种方法。 但请注意,实现可能随时发生变化,并且通过针对实现细节进行自己的实现,而不是接口可能会在将来导致一些不可预测的问题。
测试数据完整性
我知道很难相信,但DateFormat.format()实际上修改了DateFormat的状态。 例如,对于SimpleDateFormat:
// Called from Format after creating a FieldDelegate private StringBuffer format(Date date, StringBuffer toAppendTo, FieldDelegate delegate) { // Convert input date to time field list calendar.setTime(date);
其中calendar
是DateFormat的字段。
因此,我只能建议您信任该文档。 它可能知道你不知道的事情。