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.
     
     
  • 相关阅读:
    26_为什么我的删除刷新没有办法删除动态添加的数据呢?
    075_not in (null):这代表是什么意思呢?
    074_form表单中的value值
    025_回调函数没有遍历出数据
    073_模糊查询
    072_jsp追加与刷新数据
    071_为什么要catch return.setCode()?
    070_jstl中的三目表达式
    069_都是查询语句时得事物?
    打印周报模板
  • 原文地址:https://www.cnblogs.com/kid551/p/4653930.html
Copyright © 2011-2022 走看看