单例模式
饿汉式(静态变量)
- 无线程同步问题
- 类加载时已完成实例化,可能造成内存浪费(该对象从未使用)
//饿汉式(静态变量)
class SingleTon{
//私有构造器
private SingleTon(){}
private static final SingleTon SINGLE_TON = new SingleTon();
//
public static SingleTon getSingleTon(){
return SINGLE_TON;
}
}
饿汉式(静态代码块)
class SingleTon{
//私有构造器
private SingleTon(){}
private static SingleTon SINGLE_TON;
static{
SINGLE_TON = new SingleTon();
}
public static SingleTon getSingleTon(){
return SINGLE_TON;
}
}
懒汉式
线程不安全
//懒汉式(线程不安全)
class SingleTon{
//私有构造器
private SingleTon(){}
private static SingleTon SINGLE_TON;
//调用方法时再实例化对象
public static SingleTon getSingleTon(){
if(SINGLE_TON==null){
SINGLE_TON = new SingleTon();
}
return SINGLE_TON;
}
}
线程安全
- 效率低,多线程情况下同步造成效率低
////懒汉式(线程安全)
class SingleTon{
//私有构造器
private SingleTon(){}
private static SingleTon SINGLE_TON;
//调用方法时再实例化对象(同步代码解决线程安全问题)
public synchronized static SingleTon getSingleTon(){
if(SINGLE_TON==null){
SINGLE_TON = new SingleTon();
}
return SINGLE_TON;
}
}
双重检查
- 推荐使用
//双重检测,线程安全 推荐使用
class SingleTon{
//私有构造器
private SingleTon(){}
private static volatile SingleTon SINGLE_TON;
//调用方法时再实例化对象
public static SingleTon getSingleTon(){
if(SINGLE_TON==null){ //避免同步抢锁浪费效率
synchronized (SingleTon.class){
if(SINGLE_TON==null){
SINGLE_TON = new SingleTon();
}
}
}
return SINGLE_TON;
}
}
静态内部类
- 懒加载
- 线程安全
- 推荐使用
//静态内部类
class SingleTon{
//私有构造器
private SingleTon(){}
private static volatile SingleTon SINGLE_TON;
//静态内部类(只会被实例化一次,调用时才会被实例化)
private static final class SingleObject{
private static final SingleTon SINGLE_TON = new SingleTon();
}
//调用方法时再实例化对象
public static SingleTon getSingleTon(){
return SingleObject.SINGLE_TON;
}
}
枚举
- 线程安全
- 可防止反序列化重新创建新的对象
- 推荐使用
enum SingleTon{
INSTANCE;
}
//测试,输出true
SingleTon singleTon = SingleTon.INSTANCE;
SingleTon singleTon2 = SingleTon.INSTANCE;
System.out.println(singleTon==singleTon2);
JDK中的Runtime采用单例模式,部分源码如下:
public class Runtime {
private static Runtime currentRuntime = new Runtime();
/**
* Returns the runtime object associated with the current Java application.
* Most of the methods of class <code>Runtime</code> are instance
* methods and must be invoked with respect to the current runtime object.
*
* @return the <code>Runtime</code> object associated with the current
* Java application.
*/
public static Runtime getRuntime() {
return currentRuntime;
}
/** Don't let anyone else instantiate this class */
private Runtime() {}
}