zoukankan      html  css  js  c++  java
  • Multiton & Singleton

    From J2EE Bloger http://j2eeblogger.blogspot.com/2007/10/singleton-vs-multiton-synchronization.html

    1. Classic Java singleton synchronization problem

    public class Singleton {
    	private static Singleton instance;
    
    	/** Prevents instantiating by other classes. */
    	private Singleton(){}
    
    	public static synchronized Singleton getInstance() {
    		if (instance == null){
    			instance = new Singleton();
    		}
    		
    		return instance;
    	}
    }
    

    The synchronized keyword on the getInstance() method is the evil. In a multi-thread environment, every thread will be blocked by each other when trying to grab the singleton instance. This is the classic java singleton synchronization problem.

    2. The traditional solution using a static variable.

    public class Singleton {
    	/** Prevents instantiating by other classes. */
    	private Singleton() {}
    	
    	private final static Singleton instance = new Singleton();
    	
    	public static Singleton getInstance() {
    		return instance;
    	}
    }
    

    The singleton instance is initialized during the class loading time. No synchronization is necessary on the getInstance level.

    3. The classic synchronized multiton.

    public class Multiton {
    	private static final HashMap<Object, Multiton> instances = new HashMap<Object, Multiton>();
    
    	private Multiton(){}
    
    	public static Multiton getInstance(Object key){
    		synchronized (instances) {
    		// Our "per key" singleton
    		Multiton instance;
    		if ((instance = instances.get(key)) == null) {
    			// Lazily create instance and add it to the map
    			instance = new Multiton();
    			instances.put(key, instance);
    		}
    		
    		return instance;
    		}
    	}
    }
    

    The Multiton pattern begins with the concept of the Singleton pattern and expands it into an object pool of keys to objects. Instead of having a single instance per runtime, the Multiton pattern ensures a single instance per key. It simplifies retrieval of shared objects in an application.

    As we noticed from the above scriptlet, the access to the getInstance() method is synchronized to ensure the uniqueness of instance per key. This, again, is a performance bottleneck in multi-thread environment. The traditional 'static' solution for Singleton pattern can't be used here since the keys are passed into the Multiton on-the-fly. We have no way to predict how many keys will be passed into the Multiton during the runtime.
     
     
    4. The double-check locing solution
    public class Multiton {
    	private static final HashMap<Object, Multiton> instances = new HashMap<Object, Multiton>();
    
    	public static Multiton getInstance(Object key) {
    		// Our "per key" singleton
    		Multiton instance;
    	 
    		if ((instance = instances.get(key)) == null) {
    			synchronized(instances) {
    				if ((instance = instances.get(key)) == null) {
    					instance = new Multiton();
    					instances.put(key, instance);
    				}
    			}
    		}
    		
    		return instance;
    	}
    }
    

    Yes the double-checked locking does not work for Singleton (http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html), but it does work for our Multiton pattern. Reason? We have our intermediate HashMap object sits in between. Actually we can use the HashMap to solve the Singleton double-checked locking problem as well, if we don't already have the more elegant solution using a static variable.

    5. An alternative solution: Using the Java 5 ConcurrentMap

    public class Multiton {
    	private static final ConcurrentMap<Object, Multiton> instances = new ConcurrentHashMap<Object, Multiton>();
    
    	public static Multiton getInstance(Object key) {
    		// Our "per key" singleton
    		if (instances.get(key) == null) {
    			// Lazily create instance and try to add it to the map
    			Multiton instance = new Multiton();
    			instances.putIfAbsent(key, instance);
    		}
    		
    		return instances.get(key);
    	}
    }
    

    The Java 5 ConcurrentMap.putIfAbsent(), being an atomic operation, returns the previous value associated with the key instead of the new suggested value. This ensures the uniqueness of the Multiton instance inside the ConcurrentMap.

    In this solution, before a key object has been associated with a Multiton object, if two or more threads are trying to retrieve the instance with the same key object, it's possible that multiple Multiton instance will be created inside the if() block. However, the ConcurrentMap ensures that a same Multiton instance is  to be returned to the caller. Extra instances are eligible for Garbage Collection as soon as the method returns. You may not want to use this solution if the creation of the Multiton instance is an expensive operation, as in certain situation.
     
     
  • 相关阅读:
    Vue 获取dom元素中的自定义属性值
    php文件包含
    php数组运算符
    管理一组事物的状态
    php数据类型转换
    php函数
    PHP循环while do while循环
    php的流程控制 if elseif swich case for循环
    php的工作原理
    python算数、逻辑运算,位运算
  • 原文地址:https://www.cnblogs.com/kid551/p/4653930.html
Copyright © 2011-2022 走看看