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.
 
 

Multiton & Singleton的更多相关文章

  1. 23种设计模式--单例模式-Singleton

    一.单例模式的介绍 单例模式简单说就是掌握系统的至高点,在程序中只实例化一次,这样就是单例模式,在系统比如说你是该系统的登录的第多少人,还有数据库的连接池等地方会使用,单例模式是最简单,最常用的模式之 ...

  2. 设计模式之单例模式(Singleton)

    设计模式之单例模式(Singleton) 设计模式是前辈的一些经验总结之后的精髓,学习设计模式可以针对不同的问题给出更加优雅的解答 单例模式可分为俩种:懒汉模式和饿汉模式.俩种模式分别有不同的优势和缺 ...

  3. PHP设计模式(四)单例模式(Singleton For PHP)

    今天讲单例设计模式,这种设计模式和工厂模式一样,用的非常非常多,同时单例模式比较容易的一种设计模式. 一.什么是单例设计模式 单例模式,也叫单子模式,是一种常用的软件设计模式.在应用这个模式时,单例对 ...

  4. The Java Enum: A Singleton Pattern [reproduced]

    The singleton pattern restricts the instantiation of a class to one object. In Java, to enforce this ...

  5. 最适合作为Java基础面试题之Singleton模式

    看似只是最简单的一种设计模式,可细细挖掘,static.synchronized.volatile关键字.内部类.对象克隆.序列化.枚举类型.反射和类加载机制等基础却又不易理解透彻的Java知识纷纷呼 ...

  6. 每天一个设计模式-4 单例模式(Singleton)

    每天一个设计模式-4 单例模式(Singleton) 1.实际生活的例子 有一天,你的自行车的某个螺丝钉松了,修车铺离你家比较远,而附近的五金店有卖扳手:因此,你决定去五金店买一个扳手,自己把螺丝钉固 ...

  7. Qt 中使用Singleton模式需小心

    在qt中,使用Singleton模式时一定要小心.因为Singleton模式中使用的是静态对象,静态对象是直到程序结束才被释放的,然而,一旦把该静态对象纳入了Qt的父子对象体系,就会导致不明确的行为. ...

  8. 设计模式之单例模式——Singleton

                        设计模式之单例模式--Singleton 设计意图: 保证类仅有一个实例,并且可以供应用程序全局使用.为了保证这一点,就需要这个类自己创建自己的对象,并且对外有 ...

  9. C#面向对象设计模式纵横谈——2.Singleton 单件(创建型模式)

    一:模式分类 从目的来看: 创建型(Creational)模式:负责对象创建. 结构型(Structural)模式:处理类与对象间的组合. 行为型(Behavioral)模式:类与对象交互中的职责分配 ...

随机推荐

  1. jQuery in action 3rd - Working with properties, attributes, and data

    properties properties 是 JavaScript 对象内在的属性,可以进行动态创建,修改等操作. attributes 指的是 DOM 元素标记出来的属性,不是实例对象的属性. 例 ...

  2. Java猜拳小游戏(剪刀、石头、布)

    1.第一种实现方法,调用Random数据包,直接根据“1.2.3”输出“剪刀.石头.布”.主要用了9条输出判断语句. import java.util.Random; import java.util ...

  3. checked属性

    使用checked属性,你可以设置复选按钮和单选按钮默认被选中. 为此,只需在input元素中添加属性checked <input type="radio" name=&qu ...

  4. velocity模板入门

    $!{velocityCount}  随机

  5. Zookeeper会话

    Zookeeper会话的状态可以分为以下四种:CONNECTING,CONNECTED,CLOSED和NOT_CONNECTED.下图展示了会话的状态和状态之间的转移过程: 会话的初始状态为NOT_C ...

  6. [转]Python 中的 lambda,filter,map,reduce,apply

    1. lambda 1. 基本形式: 函数名=lambda args1,args2,...,argsn:expression与C语言中的宏定义类似 2. Code isodd = lambda x: ...

  7. QC11客户端安装

    win10使用hp qc11 步骤1:安装vcredist_x86,32位 步骤2:安装浏览器客户端 ALMExplorerAddIn,11版本 可能遇到的问题 1. 出现Initialization ...

  8. Linux之源码包安装软件

    安装准备      安装c语言编辑器 gcc      压缩包  node-v6.2.0-linux-x64.tar.gz   源码包保存位置  /usr/local/src/ 源码包安装位置 /us ...

  9. angular代码分析之异常日志设计

    angular代码分析之异常日志设计 错误异常是面向对象开发中的记录提示程序执行问题的一种重要机制,在程序执行发生问题的条件下,异常会在中断程序执行,同时会沿着代码的执行路径一步一步的向上抛出异常,最 ...

  10. Windows Phone 8.1 开发技术概览 (Universal APP)

    前一阵真的比较懒 WP8.1 已经出来这么长时间了现在才更新BLOG让大家久等了,今天我先为大家介绍下 WP 8.1的开发框架,什么是微软所推崇的 Universal APP,以及我们要开发 Univ ...