单例模式分为两种:饿汉式和懒汉式(饱汉式)。
饿汉式:类加载的时候已经创建好了对象,随使随用。
创建步骤
1. 构造方法私有化,从外界不能构造此类的对象
2. 静态私有变量 并初始化,类加载的时候已经被初始化
3. 提供一个静态的公共的方法供外界访问
懒汉式(饱汉式):什么时候用,再创建对象.需要注意线程安全问题,有延迟加载的特性。
创建步骤
1.构造方法私有化,从外界不能构造此类的对象
2.静态私有变量,没有被显示初始化,只是默认的null值
3.线程安全地获得静态私有对象变量的值
开发中常用饿汉式,代码简洁,没有线程安全问题
JDK中的单例模式:Runtime类的源码如下图所示
显而易见Runtime类是使用了饿汉式的单例模式
饿汉式:适用于单线程、多线程
package siglepattern;
/**
* 饿汉式 没有线程安全问题
* @author feige
*/
public class StudentHungerPattern {
//构造方法私有化
private StudentHungerPattern(){
}
//静态私有变量 并初始化
private static StudentHungerPattern student=new StudentHungerPattern();
//静态的公共的方法供外界访问,来获得对象
public static StudentHungerPattern getStudent(){
return student;
}
}
适用于单线程的懒汉式
package siglepattern;
//单线程下的延迟加载(懒汉式)
public class UnSafeLazyInitialization {
private static Instance instance=null;
public static Instance getInstance(){
if(instance==null){
instance=new Instance();
}
return instance;
}
//构造方法私有化
private UnSafeLazyInitialization(){}}
适用于多线程的懒汉式(效率不高)
package siglepattern;
/**
* 懒汉式(饱汉式)
* @author feige
*/
public class StudentFill {
private StudentFill(){}//构造方法私有化,
private static StudentFill student=null;
public synchronized static StudentFill getStuddent(){//注意线程安全
if(student==null){
student=new StudentFill();
}
return student;
}
}
由于对getStudent()方法作了同步处理,synchronized将导致性能开销
多线程下懒汉式的同步处理优化---》安全的双重检查锁定
1.volatile(适用于实例字段、静态字段的初始化)
package siglepattern;
public class SafeDoubleChekedLocking {
private volatile static Instance instance=null;
public static Instance getInstance(){
if(instance==null){
synchronized(SafeDoubleChekedLocking.class){
if(instance==null){
instance=new Instance();
}
}
}
return instance;
}
private SafeDoubleChekedLocking(){}
}
2.基于类初始化(适用于静态字段的初始化)
package siglepattern;
public class InstanceFactory {
private static class InstanceHolder{
public static Instance instance=new Instance();
}
public static Instance getInstance(){
return InstanceHolder.instance;
}
}
我们一般使用volatile对实例字段进行初始化,静态字段的初始化用基于类初始化