这篇文章的主要讨论是关于Java多线程中全局对象和局部对象的线程安全性问题。很多人认为局部对象一定是“线程安全”的,但实际上情况并不是这样的。
对于局部对象,虽然每个线程都有自己的副本,但如果多个线程同时对同一个对象进行读写操作,也会出现线程安全问题。这是因为多个线程同时对同一个对象进行操作时,可能会修改同一个变量,导致数据不一致或者出现竞态条件。为了解决这个问题,可以使用ThreadLocal类来保证线程安全,或者严格遵循开闭原则中的**“闭”**
public abstract class Test {
public void bar() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
foo(sdf);
}
public abstract foo(SimpleDateFormat sdf);
}
public void foo(SimpleDateFormat sdf) {
String dateStr = "1999-10-11 00:00:00";
for (int i = 0; i < 20; i++) {
new Thread(() -> {
try {
sdf.parse(dateStr);
} catch (ParseException e) {
e.printStackTrace();
}
}).start();
}
}
从以上例子可以看出,当一个局部变量暴露给外部,就有可能造成线程安全问题
总的来说,局部变量也就相当于小型的“全局变量”,只是正常情况下,局部变量不会暴露给外部,但是一旦出现了上述的抽象方法传递到的参数为局部变量,从而暴露给外部就有可能出现不可预知的线程安全问题,这类方法,我们也称为外星方法。在进行项目开发时,如果涉及到类线程安全问题,尽量避免将局部变量暴露给外部,以防出现问题。