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. oracle exists

    公司项目中有用到exists,感觉挺有用的,拷贝一些感念的东西. “exists”和“in”的效率问题 1) select * from T1 where exists(select 1 from T ...

  2. 【Thinking in Java】组合、继承和代理的区别

    三者的定义: 组合:在新类中new 另外一个类的对象,以添加该对象的特性. 继承:从基类继承得到子类,获得基类的特性. 代理:在代理类中创建某功能的类,调用类的一些方法以获得该类的部分特性. 使用场合 ...

  3. 使用OFBIZ 时,使用的键入提示。

    对商品的键入提示 ,效果如图(当输入关键字时,会提示出相应的数据) 首先要引入相应的插件 页面字段 js方法

  4. JBOSS内存参数详解

    JAVA_OPTS="$JAVA_OPTS -server -Xms1024m -Xmx1024m -Xss512k -XX:PermSize=128m -XX:MaxPermSize=25 ...

  5. Linq to Sql 聚合查询

    //输出体重最大的同学,并要求最大体重得大于39,并按照体重大下,对分组结果进行排序. var result = from query in linq.Student group query by q ...

  6. 用python2.7,采集新浪博客

    #coding=utf-8 #新浪博客 import urllib import re import os url=['']*1500 #每一骗博客的地址 title=['']*1500 #每一篇博客 ...

  7. windows编程:资源和播放声音

    要播放声音,要附加项:winmm.lib,然后包含头文件:#include <mmsystem.h> 播放声音用PlaySound函数,只能播放midi和wav波形文件. #define ...

  8. Linux内核--网络栈实现分析(五)--传输层之UDP协议(上)

    本文分析基于Linux Kernel 1.2.13 原创作品,转载请标明出处http://blog.csdn.net/yming0221/article/details/7532512 更多请看专栏, ...

  9. 用c解决的小题目

    判断计算机的大.小端存储方式 1 int main() { ; char* p=(char*)&a; ) printf("little\n");//小端存储:高位存在地地址 ...

  10. 使用pango-Cairo列出系统中的有效字体

    使用pango-Cairo列出系统中的有效字体,代码来源于gtk-app-devel-list fonts list using pango #include <glib.h> #incl ...