实例控制的类和多线程

the*_*hee 4 java multithreading multiton

Effective Java第2章中,项目1 Bloch建议考虑使用静态工厂方法而不是构造函数来初始化对象.他提到的好处是这个模式允许类从重复的调用返回相同的对象:

静态工厂方法从重复调用返回同一对象的能力允许类在任何时候保持对存在的实例的严格控制.执行此操作的类称为实例控制.编写实例控制类有几个原因.实例控制允许类保证它是单例(第3项)或不可实例化(第4项).此外,它允许不可变类(第15项)保证不存在两个相等的实例:a.equals(b)当且仅当a == b时.

这种模式在多线程环境中如何工作?例如,我有一个应该由实例控制的不可变类,因为一次只能存在一个具有给定ID的实体:

public class Entity {

    private final UUID entityId;

    private static final Map<UUID, Entity> entities = new HashMap<UUID, Entity>();

    private Entity(UUID entityId) {
        this.entityId = entityId;
    }

    public static Entity newInstance(UUID entityId) {
        Entity entity = entities.get(entityId);
        if (entity == null) {
            entity = new Entity(entityId);
            entities.put(entityId, entity);
        }
        return entity;
    }

}
Run Code Online (Sandbox Code Playgroud)

如果我newInstance()从分离的线程调用会发生什么?如何让这个类线程安全?

com*_*der 8

使newInstance同步

public static synchronized Entity newInstance(UUID entityId){
     ...
}
Run Code Online (Sandbox Code Playgroud)

所以一个线程进入新的实例方法,除非第一个线程完成,否则没有其他线程可以调用此方法.基本上发生的是第一个线程获得整个类的锁.对于第一个线程持有类的锁的时间,没有其他线程可以为该类输入同步的静态方法.