无状态与线程安全

最近在读《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 listDemomodifyList方法的调用并无改变FakeStateless这个对象自己的状态。因此对FakeStateless对象而言,它自身是无状态的,也是线程安全的。 less

参考资料:dom

相关文章
相关标签/搜索