[设计模式]2.单例模式
来源:互联网 发布:2017域名排行榜 编辑:程序博客网 时间:2024/05/27 00:32
一、单例模式简介
单例模式(Singleton)是一种常用的设计模式,其定义是单例对象的类只能允许一个实例存在。该类创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
二、单例模式的基本实现思路
单例模式要求类能够返回同一个对象的实例,和获取该对象的方法(必须是静态方法,通常使用getInstance来命名)。
单例实现的主要步骤
1.私有的(private)构造方法,让其他代码无法通过调用该类的构造方法来实例化这个对象,只能通过提供的静态方法来得到该类的唯一实例。
2.调用提供的静态方法时,该类的对象的引用不为空时返回该实例对象的引用,否则实例化再返回该类的引用。
三、使用单例模式的注意事项
单例模式在多线程的应用场合中使用需要小心。因为当多个线程同时调用创建方法是,实例还没被创建。则会同时创建一个实例。这样会导致多个实例创建出来,这样就违反了实例唯一的原则。为了解决这个问题需要为已经实例化的变量提供一个互斥锁,但是这样做会降低效率。
三、单例的具体实现
1.饿汉式(静态常量)[可用]
package com.devil;/** * 饿汉式(静态常量) * Created by wangdi on 2016/12/11. */public class Singleton1 { private static final Singleton1 SINGLETON = new Singleton1(); private Singleton1(){}; public static Singleton1 getInstance(){ return SINGLETON; }}
优点:
写法简单,在类加载时就完成了对象的实例化,避免了下城同步问题。
缺点:
因为在类已加载时就创建了对象,并没有在需要的时候才创建,导致资源浪费。
2.饿汉式(静态代码块)[可用]
package com.devil;/** * 饿汉式(静态代码块)[可用] * Created by wangdi on 2016/12/11. */public class Singleton2 { private static Singleton2 instance; static { instance = new Singleton2(); } private Singleton2() {} public static Singleton2 getInstance() { return instance; }}
与饿汉式(静态常量)方式类似,只不过把类的实例化过程发在了静态代码块中,也是在类加载的手就执行静态代码块中的代码,创建类的实例。优缺点类似。
3.懒汉式(线程不安全)[不可用]
package com.devil;/** * 懒汉式(线程不安全)[不可用] * Created by wangdi on 2016/12/11. */public class Singleton3 { private static Singleton3 instance; private Singleton3() {} public static Singleton3 getInstance(){ if (null == instance) { instance = new Singleton3(); } return instance; }}
优点:
在创建时才创建实例,起到了lazy loding的效果。
缺点
在多个线程调用时会创建多个实例。不能在多线程中使用这种方式。
4.懒汉式(线程安全,同步方法)[不推荐使用]
package com.devil;/** * 懒汉式(线程安全,同步方法)[不推荐使用] * Created by wangdi on 2016/12/11. */public class Singleton4 { private static Singleton4 instance; private Singleton4() { } public static synchronized Singleton4 getInstance() { if (null == instance) { instance = new Singleton4(); } return instance; }}
为了解决第三种方法中线程不安全问题,在创建实例的方法上做了线程同步。
缺点:
在每个线程要获得该类的实例时,执行getInstance方法都进行了同步。
但是其实这个方法只需要进行一次实例化,后面想要获得该类的实例,直接return就行。方法进行同步效率太低。
5.懒汉式(线程安全,同步代码块)[不可用]
package com.devil;/** * 懒汉式(线程安全,同步代码块)[不可用] * Created by wangdi on 2016/12/11. */public class Singleton5 { private static Singleton5 instance; private Singleton5() { } public static Singleton5 getInstance() { if (null == instance) { synchronized (Singleton5.class) { instance = new Singleton5(); } } return instance; }}
由于第四种方式同步方法的效率太低了。所以放弃同步方法。改为同步实例创建时的代码块.但是这种同步并不能起到线程同步的作用。和在使用第三种方式时遇到的问题一样,一个线程进行if (null == instance) 时,还未来得及往下执行,另一个线程也通过了这个判断语句,这时就会产生多个实例。
6.双重检查
package com.devil;/** * 双重检查[推荐使用] * Created by wangdi on 2016/12/11. */public class Singleton6 { private volatile static Singleton6 instance; private Singleton6() { } public static Singleton6 getInstance() { if (null == instance) { synchronized (Singleton6.class) { if (null == instance) { instance = new Singleton6(); } } } return instance; }}
这种方式是在第五种方式基础上的升级,实现了线程安全和lazy loding。效率较高
7.内部静态类[推荐用]
package com.devil;/** * 内部静态类[推荐用] * Created by wangdi on 2016/12/12. */public class Singleton7 { private Singleton7() { } private static class SingletonInstance { private static final Singleton7 INSTANCE = new Singleton7(); } public static Singleton7 getInstance() { return SingletonInstance.INSTANCE; }}
只有在调用getInstance方法时调用了SingletonInstance类时,对象才会实例化。类的静态熟悉只会在第一次类加载的时候初始化。避免了线程不安全,延迟加载,效率高。
8.枚举[推荐用]
package com.devil;/** * 枚举[推荐用] * Created by wangdi on 2016/12/12. */public enum Singleton8 { INSTANCE; private Singleton8(){ }}
枚举是在JDK1.5后引入的,在现在大家普遍使用JDK1.7和JDK1.8来开发的,推荐使用枚举来实现单例模式。不仅可以避免线程同步问题,而且还能防止反序列化重新创建新的对象。
示例代码:https://github.com/code-wangdi/Design-Patterns 中的Singleton-Pattern
- 2.设计模式之单例模式
- [设计模式]2.单例模式
- 设计模式------单例模式
- 设计模式------单例模式
- 设计模式-单例模式
- 设计模式 - 单例模式
- 设计模式---单例模式
- 设计模式---单例模式
- 【设计模式】单例模式
- 设计模式-单例模式
- 设计模式----单例模式
- 设计模式--单例模式
- 设计模式-单例模式
- 设计模式-单例模式
- [设计模式] 单例模式
- 设计模式--单例模式
- 设计模式---单例模式
- 设计模式--单例模式
- Tab切换(高级版)
- hadoop常用运维命令及相关说明
- 浅克隆与深克隆
- view设置透明度
- 40个重要的HTML5面试题及答案
- [设计模式]2.单例模式
- Eclipse 设置断点无效、不能debug
- 解答”打包成功后的apk不能和后台服务进行数据交互“的问题
- java运行时异常和编译时异常的区别
- tableviewcell的单选和多选
- RecycleView的基本配置和使用方法(三)---RecycleView中 item的事件处理
- freeradius 如何配置pam 模块
- 你说这里都是我的喜欢
- 解决adb offline 问题