单例模式(Singleton Pattern)

单例模式定义:Ensure a class has only one instance,and provide a global point of access to it.(确保某一个类只有一个实例,自行实例化并提供一个全局访问点)

以下实现方式在多线程环境下都是没有问题的

实现一(对getInstance()方法进行同步,影响性能):

public class Singleton {
	private static Singleton instance = null;
	
	private Singleton(){}
	
	public synchronized static Singleton getInstance(){
		if(null == instance){
			instance = new Singleton();
		}
		return instance;
	}
}
public class Singleton {
	private static Singleton instance = null;
	
	private Singleton(){}
	
	public static Singleton getInstance(){
		synchronized(Singleton.class){
			if(null == instance){
				instance = new Singleton();
			}
			return instance;
		}
	}
}

 

实现二(推荐方式):

instance可以是final的,也可以不是,我个人认为没什么影响

public class Singleton {
	private static Singleton instance = new Singleton();
	//private final static Singleton instance = new Singleton();也是可以的
	
	private Singleton(){}
	
	public static Singleton getInstance(){
		return instance;
	}
}

虚拟机将自动进行同步,详见:http://blog.csdn.net/a19881029/article/details/17068191

 

实现三:

过一段时间回来看这种实现方式,简直蠢透了,给自己提个醒,留在这里不删了,这种实现方式的问题如下:

1,instance参数既然使用了static修饰符,为什么还要使用volatile修饰符?

2,在同步方法getInstance的方法体内再次同步还有什么意义?

将方法本身的同步去掉,保留方法体内的同步可能是有意义的(减少同步范围),但是完全不能确定instance == null这步判断是否会产生原子性问题

虚拟机规范没有明确规定引用类型(reference,指向一个对象)占用32位还是占用64位(跟虚拟机具体实现有关),如果占用32位,则不会有原子性问题,如果占用64位,虚拟机需要分2次分别获取2个Slot内保存的值以得到一个完整的引用类型,此时将产生原子性问题(参考long和double)

public class Singleton {
	private static volatile Singleton instance;
	
	private Singleton(){
		System.out.println(Math.random());
	}
	
	public synchronized static Singleton getInstance(){
		if(null == instance){
			synchronized (Singleton.class) {
				instance = new Singleton();
			}
		}
		return instance;
	}
}

具体思想就是同步块内代码量越少,代码处理的速度越快,同步对性能的影响越小

jdk1.4及以下版本volatile变量的实现会导致该实现出现bug

 

单例模式也可以生成多个实例:

package com.test;

import java.util.Random;
import java.util.Vector;

public class Connection {
	private static int max_num = 10;
	private static int num_count = 0;
	private static Vector<Connection> connPool = new Vector<Connection>();
	
	static{
		for( ; num_count < max_num ; num_count++){
			Connection conn = new Connection();
			System.out.println(num_count+":"+conn.hashCode());
			connPool.add(conn);
		}
	}
	
	private Connection(){}
	
	public static Connection getConn() throws Exception{
		Random random = new Random();
		int num = random.nextInt(max_num);
		Connection conn = connPool.get(num);
		System.out.println(conn.hashCode());
		return conn;
	}
	
	public static void main(String[] args) throws Exception{
		for(int i = 0 ; i<5 ; i++){
			Connection.getConn();
		}
	}
}
0:3526198 
1:7699183 
2:14285251 
3:10267414 
4:27553328 
5:4072869 
6:1671711 
7:11394033 
8:4384790 
9:9634993 
10267414
1671711
1671711
4072869
4384790
posted @ 2013-06-03 13:48  心意合一  阅读(128)  评论(0编辑  收藏  举报