最近在读《Java并发编程实战》这本书时,其中有一句话显示:java
无状态对象必定是线程安全的
当时就产生了怀疑,写一段代码举例:编程
public class ListDemo { public List<Integer> nums = Lists.newArrayList(1, 2, 3); @Override public String toString() { return "nums=" + nums; } } public class FakeStateless { public void modifyList(ListDemo listDemo) { listDemo.nums.add(LocalTime.now().getNano()); System.out.println(this.getClass().getName() + listDemo); } } public class App { public static Random random = new Random(); public static void main(String[] args) throws InterruptedException { ListDemo listDemo = new ListDemo(); FakeStateless A = new FakeStateless(); FakeStateless B = new FakeStateless(); new Thread(() -> { sleepRandomTime(); A.modifyList(listDemo); // nums=[1, 2, 3, 918000000] }).start(); new Thread(() -> { sleepRandomTime(); B.modifyList(listDemo); // nums=[1, 2, 3, 918000000, 680000000] }).start(); Thread.sleep(2000); System.out.println("main" + listDemo); // nums=[1, 2, 3, 918000000, 680000000] } private static void sleepRandomTime() { try { Thread.sleep(random.nextInt(1000)); } catch (InterruptedException e) { e.printStackTrace(); } } }
而后说:看!ListDemo listDemo
根本就不线程安全。但真的是这样吗?《Effective Java》和《Java并发编程实战》两本书的做者有必要骗人吗? 安全
咱们再回来看看无状态的定义:并发
Stateless object is an instance of a class without instance fields (instance variables). The class may have fields, but they are compile-time constants (static final).
// 无状态对象是没有实例字段(实例变量)的类的实例。该类可能具备字段,可是它们是编译时常量(静态final)。
等下!咱们这里说的无状态对象是FakeStateless
这个对象,不是它操做的ListDemo listDemo
. 如今看来,是无状态对象FakeStateless
的一个方法modifyList
在操做一个不属于本身实例变量的有状态对象ListDemo listDemo
。 modifyList
方法的调用并无改变FakeStateless
这个对象自己的状态。因此对FakeStateless
对象而言,它自身是无状态的,也是线程安全的。 less
参考资料:dom