一、单例概念
单例模式是一种对象创建模式,它用于产生一个对象的具体实例,它可以确保系统中一个类只产生一个实例
二、好处
1、对应频繁使用的对象,可以省略创建对象所花费的时间,对于那些重量级对象而言,是非常客观的一笔系统开销。
2、由于new操作次数减少,因此对系统内存的使用频率也会降低,这将减少GC压力,缩短GC停顿时间
三、单例的六种写法和各自的特点
饿汉/懒汉/懒汉线程安全/DCL/静态内部类/枚举
1.饿汉
public class HungrySingleton {
//1.实例化变量是静态的
private static HungrySingleton singleton = new HungrySingleton();
//2.构造方法是私有的
private HungrySingleton(){
//一旦使用此方法立马被调用
}
//获取实例的方法是静态的
public static HungrySingleton getHungrySingleton(){
return singleton;
}
}
缺点:即使没有使用这个类都会被初始化,如果初始化内容比较多的话,对性能的影响是很大的
无法对instance实例做延迟加载
2.懒汉模式
public class LazySingleton {
public static LazySingleton singleton;
//构造方法是私有的
private LazySingleton(){}
public static LazySingleton getSingleton(){
if (singleton==null){
//第一次创建时会被初始化
singleton = new LazySingleton();
}
return singleton;
}
}
缺点:(并非同步)多线程的并非这样的实现是无法保证实例是唯一的
3.懒汉线程安全模式
public class LazySafeSingleton {
public static LazySafeSingleton safeSingleton;
private LazySafeSingleton(){}
//方法中声明synchronized关键字(方法一)
public synchronized static LazySafeSingleton getSafeSingleton(){
if (safeSingleton==null){
safeSingleton = new LazySafeSingleton();
}
return safeSingleton;
}
//同步代码块的实现(方法二)
public static LazySafeSingleton getInstance(){
synchronized (LazySafeSingleton.class){
if (safeSingleton==null){//
safeSingleton = new LazySafeSingleton();
}
}
return safeSingleton;
}
}
缺点:性能(synchronized关键字)上的缺点,每次只有一个线程读取实例
4.DCL(double check lock)双重检查锁设计模式
public class DCLSingleton {
private static volatile DCLSingleton singleton;
private DCLSingleton(){}
public static DCLSingleton getInstance(){
//避免不必要的同步
if (singleton==null){
//同步
synchronized (DCLSingleton.class){
//在第一次调用时初始化
if (singleton==null){
singleton = new DCLSingleton();
}
}
}
return singleton;
}
}
//可能会有多个线程一起进入同步代码块外的情况,如果不检验的话就会生成多个实例,就成了
懒汉模式中的缺点
//缺点:JVM的即时编译器中存在指令重排序的优化(volatile)优化
5.静态内部类单例设计模式
public class StaticSingleton {
private StaticSingleton(){}
public static StaticSingleton getInStance(){
return Singler.singleton;
}
//静态内部类
private static class Singler{
private static final StaticSingleton singleton = new StaticSingleton();
}
}
//优点:jvm本身机制保证了线程安全/没有性能缺陷
原因:static/final(初始化之后无法被修改)
6.枚举单例设计模式(java5之后)
public enum EnumSingleton {
//定义一个枚举的元素,它是singleton的实例
INSTANCE;
public void doSomething(){
}
}
优点:写法简单/线程安全