Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/391.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 最佳实践:具有延迟初始化的线程安全多通模式_Java_Thread Safety_Multiton - Fatal编程技术网

Java 最佳实践:具有延迟初始化的线程安全多通模式

Java 最佳实践:具有延迟初始化的线程安全多通模式,java,thread-safety,multiton,Java,Thread Safety,Multiton,其思想是创建一个工厂类,该类根据“类型”返回不同的单例实例。[Multiton模式]。此外,应延迟创建单例实例 下面的代码是线程安全的吗?使用ConcurrentHashMap使它更简单,但我想尝试使用HashMap public class Multiton { private HashMap<String, Interface> interfaceMap; private static class Holder { public static

其思想是创建一个工厂类,该类根据“类型”返回不同的单例实例。[Multiton模式]。此外,应延迟创建单例实例

下面的代码是线程安全的吗?使用ConcurrentHashMap使它更简单,但我想尝试使用HashMap

public class Multiton {

    private HashMap<String, Interface> interfaceMap;

    private static class Holder {
        public static final Multiton INSTANCE = new Multiton();
    }

    public static Multiton getInstance() {
        return Holder.INSTANCE;
    }

    private Multiton(){
        interfaceMap = new HashMap<String, Interface>();        
    }

    public Interface getInterface(String key){
        Interface value = interfaceMap.get(key);
        if(null == value){
            synchronized(interfaceMap){
                // double check locking
                if(interfaceMap.get(key) == null){
                    switch(key){
                    case TypeA : // initialize Type A interface here and put it to map
                        value = new TypeA();
                        interfaceMap.put(key, value);
                        break;
                    case TypeB : // initialize Type B interface here and put it to map
                        value = new TypeB();
                        interfaceMap.put(key, value);
                        break;
                    }
                }
            }
        }
        return interfaceMap.get(key);
    }
}
。特别是,仅在写入映射时进行同步是不够的,因为这不会阻止读线程访问写线程当前正在修改的状态

例如,如果您不能使用ConcurrentHashMap,因为您必须确保创建一个TypeA,而不仅仅是所有客户端都使用一个TypeA,那么下面的方法应该是有效的,而且价格合理。特别是,一旦构建了惰性对象,它就没有锁了

abstract class Lazy<T> {
    private volatile T instance;

    abstract T create();

    void get() {
        if (instance == null) {
            synchronized (this) {
                if (instance == null) {
                    instance = create();
                }
            }
        }
        return instance;
    }
}

class Multiton {
    private final Map<String, Lazy<?>> map = new HashMap<>();

    Multiton() {
        map.put("A", new Lazy<A> {
            A create() {
                return new A();
            }
        }
        map.put("B", new Lazy<B> {
            B create() {
                return new B();
            }
        }
        // and so on for the other types
    }
}

生产质量,您可能想考虑使用LAMDBA表达式来处理工厂方法,并为映射键入安全的键,例如所请求接口的类对象。< / P>使用已经为您处理的Spring。应用程序是纯java应用程序。没有spring,请修改spring或其他已经处理此问题的框架中的必要源代码,以解决您的问题。另外,Spring是使用纯Java构建的。为什么要尝试使用HashMap?这是正确的。这对于Java1.4和更早版本是正确的。因为1.5 DCL工作正常。我不想投你反对票,但这个答案是错误的,你应该删除它。我链接到的文章明确指出,双重检查锁定只有在非常特定的情况下才是正确的。在这种情况下是不正确的。你链接到的文章是古老的。由于改进了Java 1.5的内存模型,这篇文章已经过时了。如果你读到最后,你可能已经发现了新Java内存模型下的部分,它正确地描述了从Java 5开始,只有通过易失性字段访问singleton以建立singleton的赋值和访问之间的“发生在之前”关系时,双重检查锁定才是安全的。您可能是对的,现在已经晚了,本文描述的是singleton,而不是multipleton。