public class SingletonTest {
private static SingletonTest instance = new SingletonTest();
//私有构造方法 只能通过 公有方法 getInstance 获得实例
private SingletonTest(){}
public static SingletonTest getInstance() {
return instance;
}
}
饿汉式在类加载时静态变量 instance 就进行初始化。资源利用率不好。
2、懒汉式:
public class SingletonTest {
private static SingletonTest instance = null;
private SingletonTest(){}
//synchronized 保证线程同步,线程安全
public static synchronized SingletonTest getInstance() {
if (instance == null) {
instance = new SingletonTest();
}
return instance;
}
}
懒汉式线程安全,在类加载时并不进行初始化,只是在调用方法getInseance() 时会进行初始化,实现了延迟加载(lazy load)。但是也就是因为只要调用 getInstance() 就会都需要进行 线程锁定判断,进行初始化资源,降低系统的性能,特别是多线程,高并发的状态下。
3、双重校验索锁定(懒汉式的改进):
双重校验是懒汉式的改进,因为当同时有2个进程a,b 调用getInstance(),当a进入 线程锁定,创建对象,b只能等a 执行完,退出来,才能进入进程同步块。但是还是不知道 a 创建对象没有。可能就会出现创建了2个对象。
public class SingletonTest {
//被volatile修饰的成员变量可以确保多个线程都能够正确处理
private volatile static SingletonTest instance = null;
private SingletonTest(){}
public static synchronized SingletonTest getInstance() {
if (instance == null) { //第一次校验
synchronized (SingletonTest.class) {
if (instance == null) { //第二次校验
instance = new SingletonTest();
}
}
}
}
}
这样还是有一个问题,就是使用volatile,由于volatile关键字会屏蔽Java虚拟机所做的一些代码的优化,可能会降低系统运行的效率。
4、静态内部类:
静态内部类是一个更好的实现方式,通过内部类创建对象,外部类进行返回。
public class SingletonTest {
private static class HolderSingleton {
private static final SingletonTest INSTANCE = new SingletonTest();
}
private Singleton (){}
public static final SingletonTest getInstance() {
return HolderSingleton .INSTANCE;
}
}
类加载时不会实例化,只有调用 内部类的 getInstance() 才会实例化,由于是静态的实例,所以创建的实例是唯一的,而且是线程安全的。
其实这就是 IoDH (Initialization Demand Holder) 技术。既可以实现延迟加载,又可以保证线程安全,不影响系统性能。
5、单个元素枚举类型:
public enum SingletonTest {
INSTANCE;
public void method() {...}
}
其实这是Joshua Bloch(Effective Java作者)的思路,这种方法更加简洁,无偿提供序列化机制,绝对防止多次序列化,即使面对复杂的序列化或反射攻击的时候。只是这只能是针对 java 1.5 以上版本的。 因为 java 1.5 才有枚举enum 新特性。
用 Joshua 的话说“单元素的枚举类型已成为实现 Singleton 的最佳方法。”
这是现在至少我很少见过这么用,以后要尝试下。
以上这些都只是我自己的一些见地,仅代表自己的看法。
原文:http://blog.csdn.net/u011845742/article/details/44680397