单例模式主要是为了避免因为创建了多个实例造成资源的浪费,且多个实例由于多次调用容易导致结果出现错误,而使用单例模式能够保证整个应用中有且只有一个实例。
- 不允许其他程序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 类型的引用所以得到它就可以调用枚举中的方法了。
面试一般都会问单例模式的懒汉式的线程安全问题。