应用场景
封装一些常用的工具类,保证整个应用常用的数据统一
保存一些共享数据在内存中,其他类随时可以读取。
创建对象耗时或者耗费资源过多,但又需要频繁用到;
需要频繁的进行创建和销毁的对象;
注意:如果写成单例模式就不要用spring注入了,spring注入默认单例,两者重复
7种方式
饿汉式
线程安全
public class Singleton { private static final Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance() { return instance; } }
线程安全,类加载的时候实例化,意思就是在初始化instance的时候就new了,所以导致资源浪费(吹毛求疵的说)
懒汉式-线程不安全
线程不安全
public class Singleton { private static Singleton instance; private Singleton() { } public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } } 首次我调用getInstance,那么就会进行类加载,这时候instance引用没被初始化。 然后进行判断空后,给instance引用初始化一个对象。 下次调用getInstance因为是不是空,直接返回。 疑问:我调用getInstance后,都会返回一个对象。饿汉式只是说初始化的时候就new了对象,而我这做了判断再new,实质上都把对象new了。那么懒汉式节省资源体现在哪? 体现在你调用类的其它方法的时候,它不会new(实例化)对象!
上代码!
懒汉式-同步方法
线程安全,同步方法
public class Singleton { private static Singleton instance; private Singleton() { } public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } } 线程安全,但效率低下!
懒汉式,双重检测
线程安全,同步代码块
public class Singleton { private static volatile Singleton instance; private Singleton() { } public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } } 兼顾效率和线程安全,可以用。但是性能不高
静态内部类(推荐)
线程安全
public class Singleton { private static Singleton instance; private Singleton() { } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } } 业务这种够用,线程安全+懒加载
枚举
线程安全
public enum Singleton { INSTANCE; } 知道就行,线程安全,防反射,防反序列化。其它方式不防!
枚举懒加载(删除)
import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class ThreadPoolUtil { private enum innerEnum { INSTANCE; private final ThreadPoolExecutor executor; private final ThreadPoolUtil threadPoolUtil; innerEnum() { ThreadPoolExecutor.CallerRunsPolicy policy = new ThreadPoolExecutor.CallerRunsPolicy(); executor = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), policy ); threadPoolUtil = new ThreadPoolUtil(); } private ThreadPoolExecutor getThreadPool() { return executor; } private ThreadPoolUtil threadPoolUtil() { return threadPoolUtil; } } public static ThreadPoolUtil getInstance() { return innerEnum.INSTANCE.threadPoolUtil(); } public ThreadPoolExecutor getThreadPool() { return innerEnum.INSTANCE.getThreadPool(); } } 这部分拿不准,先放在这里。所以说枚举到底是不是懒加载,是的话又例子论证吗?网上说法不一,搞不懂
最后再宣传一波,我的个人主页:https://www.yuque.com/yingwenerjie,在这里你将收获我的成长知识库,不限于后端、前端、生活等知识库哟~
期待和老兵合作?想知道我能为你做什么?点击这里吧!https://www.yuque.com/yingwenerjie/kp675n/ful4rt
转载合作联系老兵,私自盗用必究!