简说单例
来源:互联网 发布:西餐厅收银软件 编辑:程序博客网 时间:2024/05/22 03:31
单例方式
看到很多人写单例都不考虑线程安全,当多线程操作当时候,就可能出现多个实例,那么不就违背了单例的初衷了么?如果要维护到单例类中到成员,那就更尴尬了,我看到也实在是无奈,所以这里建议大家写单例是需要做到线程安全!!
首先说推荐单例模式写法,主流用法。
- DCL (Double CheckLock)
public class Singleton { private Singleton() { } /** * instance = new Singleton();因为不是一个原子操作,所以在编译到时候大致有三件事 * 1:给Singleton实例分配内存 * 2:调用好Sinleton() 构造函数,初始化成员字段 * 3:将instance对象指向分配到内存空间(执行了这一步后instance将为null了) * 但是: * 在JDK1.5之前有JMM(java Memory Model内存模型)中Cache、寄存器到驻内存回写顺序到规定,会导致执行顺序到不确定性 * 可能123 ,也可能132。 * 再1.5之后 JDK调整了JMM,加入了volatile关键字 * * 这里加入volatile 关键字主要是为了保证每次都从驻内存获取 */ private volatile static Singleton instance; public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) instance = new Singleton(); } } return instance; }}
DCL写法优点就是在第一次执行到时候才会实例化,效率高。缺点就是第一次加载反应稍慢,性能牺牲点。再JDK1.6以后使用,这种方式是不错的选择。
- 静态内部类写法:
private Singleton() { } private static class SingletonClassHolder { private static final Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonClassHolder.instance; }
这是种单例方式,不光延迟了实例化,效率也高,也不需要双重检查锁定,并发上,性能就上去了。
- 枚举
public enum Singleton { INSTANCE; public void doS() { Log.e("11", "11"); }}
枚举最大的优点就是简单。枚举在java种与普通类式一样的,用这种方式来做单例也式很好的,最重要的是在任何情况下,它都式线程安全的,任何情况下它都只有一个实例。
其他单例在反序列化的时候会因为readResolve方法,而重新生成对象
//其他单例实现种,反序列化需要用这种方式来避免重新生成对象private Object readResolve() throws ObjectStreamException{ return instance;}
另外 :
- 饿汉式:
private static final Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance() { return instance; }
看了前面,在看这个就明显了,在声明的时候就会实例化,也不管需不需要使用。所以一般不推荐使用,可根据应用场景选择。
- 懒汉式:
private static Singleton instance; private Singleton() { } public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }
懒汉式式做到了再需要到时候才实例化了,但是每次获取的时候都需要同步,增加了开销,一般不推荐使用这种方式。
说说反射获取
介绍了5种单例方式,不线程安全的就不在这里说了。
除了枚举以外的方式,都可以使用反射来获取对象,采用如下方式即可:
Class<?> class1 = null; try { class1 = Class.forName("com.demo.Singleton"); Method m = class1.getMethod("getInstance"); Singleton single = (Singleton) m.invoke(null); //获取到之后执行 single.doSomething(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); }
而枚举就不可以咯,会报错的。
所以枚举方式确实很不错。只是在android种不太推荐枚举,官方这样说的:
,会消耗更多的内存,影响性能问题。对手机内存不大的,是个灾难。
根据实际情况来选择对应的单例模式就可以了。
阅读全文
1 0
- 简说单例
- 饿汉,懒汉,都是单身汉!---->简说单例模式里两个基友间的二三事
- 简单的弧度角度转换
- 完美解决SwipeRefreshLayout与RecyclerView滑动冲突问题
- lightgbm_predict4j:LightGBM在线预测的java实现
- Minicom安装和使用和lte调试方法
- abstract class和interface的区别
- 简说单例
- html5<canvas在画布上画视频和图片>
- Connection接口介绍
- dialog改变大小及位置
- ubuntu或linux网卡配置/etc/network/interfaces
- PHP substr(),mb_substr(),mb_strcut的区别和用法
- CMake在linux下构建应用程序
- 根据角度计算圆的坐标点
- 第二讲 探秘微信公众号