Java 常用设计模式之单例模式

单例模式主要是为了避免因为创建了多个实例造成资源的浪费,且多个实例由于多次调用容易导致结果出现错误,而使用单例模式能够保证整个应用中有且只有一个实例。

  • 不允许其他程序new对象。构造方法私有化。
  • 其内部产生该类的实例化对象,并将其封装成private static类型。
  • 定义一个静态方法返回该类的实例。

单例模式的实现写法

1、饿汉式

类加载就初始化了,线程安全

package mistra.com.designpatterns.singleton;

/**
 * Created by Mistra-WR on 2018/1/18/018.
 */
public class Singleton {
    private static Singleton instance=new Singleton();
    private Singleton(){};
    public static Singleton getInstance(){
        return instance;
    }
}

获取实例

Singleton instance = Singleton.getInstance(); 
2、懒汉式

在调用getInstance方法的时候才创建对象
标准懒汉式>>>

package mistra.com.designpatterns.singleton;

/**
 * Created by Mistra-WR on 2018/1/18/018.
 */
public class Singleton2 {
    private static Singleton2 singleton2 = null;
    private Singleton2(){}

    public static Singleton2 getInstance(){
        if(singleton2==null){
            singleton2 = new Singleton2();
        }
        return singleton2;
    }
}

这种写法存在线程安全问题:当有多个线程去调用getInstance方法来获取Singleton的实例,那么就有可能发生这样一种情况当第一个线程在执行if(instance==null)这个语句时,此时instance是为null的进入语句。在还没有执行instance=new Singleton()时(此时instance是为null的)第二个线程也进入if(instance==null)这个语句,因为之前进入这个语句的线程中还没有执行instance=new Singleton(),所以它会执行instance=new Singleton()来实例化Singleton对象,因为第二个线程也进入了if语句所以它也会实例化Singleton对象。这样就导致了实例化了两个Singleton对象。
可以给getInstance()方法加上synchronized 来进行同步,但是效率低不推荐使用。

双重校验锁懒汉式>>>
线程安全的,推荐使用

package mistra.com.designpatterns.singleton;

/**
 * Created by Mistra-WR on 2018/1/18/018.
 */
public class Singleton3 {
    private static Singleton3 instance=null;
    private Singleton3() {};

    public static Singleton3 getInstance(){
        if (instance == null) {
            synchronized (Singleton3.class) {
                if (instance == null) {
                    instance = new Singleton3();
                }
            }
        }
        return instance;
    }
}
3、内部类方式

饿汉式只要Singleton类被装载就会实例化,没有懒加载的作用,而静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用getInstance方法,才会装载SingletonHolder类,从而完成Singleton的实例化。
类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。
线程安全,效率高,推荐使用

package mistra.com.designpatterns.singleton;

/**
 * Created by Mistra-WR on 2018/1/18/018.
 */
public class Singleton4 {
    private Singleton4() {};

    private static class SingletonHolder{
        private static Singleton4 instance=new Singleton4();
    }

    public static Singleton4 getInstance(){
        return SingletonHolder.instance;
    }
}
4、枚举式(jdk1.5+)

线程安全,最佳选择,实现非常简单而且最安全

package mistra.com.designpatterns.singleton;

/**
 * Created by Mistra-WR on 2018/1/18/018.
 */
public enum  Singleton5 {
    instance;

    private Singleton5() {}

    public void method(){
    }
}

获得实例方式

Singleton5.instance.method();  

这里的instance即为Singleton5 类型的引用所以得到它就可以调用枚举中的方法了。

面试一般都会问单例模式的懒汉式的线程安全问题。


这里写图片描述

猜你喜欢

转载自blog.csdn.net/axela30w/article/details/79097315