java 设计模式之单例模式(单线程、多线程下)

单例模式分为两种:饿汉式和懒汉式(饱汉式)

饿汉式:类加载的时候已经创建好了对象,随使随用。

            创建步骤
         1. 构造方法私有化,从外界不能构造此类的对象
         2. 静态私有变量 并初始化,类加载的时候已经被初始化
         3. 提供一个静态的公共的方法供外界访问

懒汉式(饱汉式):什么时候用,再创建对象.需要注意线程安全问题,有延迟加载的特性。

            创建步骤
        1.构造方法私有化,从外界不能构造此类的对象
        2.静态私有变量,没有被显示初始化,只是默认的null值
        3.线程安全地获得静态私有对象变量的值

开发中常用饿汉式,代码简洁,没有线程安全问题

JDK中的单例模式:Runtime类的源码如下图所示

java 设计模式之单例模式(单线程、多线程下)_第1张图片

显而易见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对实例字段进行初始化,静态字段的初始化用基于类初始化

你可能感兴趣的:(设计模式)