目录
一、为什么要使用单例模式
避免一个类的对象被频繁的创建和销毁,减少消耗系统资源。
二、单例模式有什么特点
一个类只有一个对象,且构造函数是私有的,外界无法new这个类的对象,对象只能由类的内部进行实例化,此类提供一个公有的获取实例化对象的方法供外界调用来获取对象。
三、单例模式的实现方式
1、懒汉式
懒汉式指的是只有instance为null时才创建。
从下面代码实现来看,并不是线程安全的,当多个线程同时调用getInstance方法是,可能这个时候判断instance都是null,这样这几个线程都会创建一个对象,不适合多线程。可能存在违背单例模式一个类只有一个实例的特点,所以严格意义上懒汉式的这种实现方式并不是真正的单例模式。
public class SingleLazyNoSafe {
private static SingleLazyNoSafe instance;
public static SingleLazyNoSafe getInstance() {
if (instance == null) {
instance = new SingleLazyNoSafe();
}
return instance;
}
private SingleLazyNoSafe() {
}
public void showMessage() {
System.out.println("SingleLazyNoSafe");
}
}
从下面代码看,这种懒汉式单例模式实现方式是线程安全的,在获取实例的方法上设置了同步锁synchronized。
public class SingleLazySafe {
private static SingleLazySafe instance;
public static synchronized SingleLazySafe getInstance() {
if (instance == null) {
instance = new SingleLazySafe();
}
return instance;
}
private SingleLazySafe() {
}
public void showMessage() {
System.out.println("SingleLazySafe");
}
}
2、饿汉式
饿汉式指的是不管instance是否存在,只在类加载的时候实例化一个对象,之后获取的都是这个对象,是线程安全的。
public class SingleHungry {
private static SingleHungry singleHungry = new SingleHungry();
private SingleHungry() {}
public static SingleHungry getInstance() {
return singleHungry;
}
public void showMessage() {
System.out.println("SingleHungry");
}
}
3、双检锁
双检锁,volatile、synchronized,是线程安全的。
public class SingleDouble {
private static volatile SingleDouble instance;
private SingleDouble() {}
public static SingleDouble getInstance() {
if (instance == null) {
synchronized (SingleDouble.class) {
if (instance == null) {
instance = new SingleDouble();
}
}
}
return instance;
}
public void showMessage() {
System.out.println("SingleDouble");
}
}
4、登记式/静态内部类
和饿汉式有些相同,只不过饿汉式是只要他的类加载就会实例化,但静态内部类不会,只有动态调用它的getInstance时内部类才会加载并实例化对象,之后获取得也都是这个对象,也是线程安全的。
public class SingleStatic {
private static class StaticInner{
private static SingleStatic staticInner = new SingleStatic();
}
private SingleStatic() {}
public static SingleStatic getInstance() {
return StaticInner.staticInner;
}
public void showMessage() {
System.out.println("SingleStatic");
}
}
5、枚举
被称为单例模式的最佳实现方案,线程安全。
public enum SingleEnum {
INSTANCE;
public void showMessage() {
System.out.println("SingleEnum");
}
}