经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
【Java设计模式】单例模式
来源:cnblogs  作者:菜鸡土豆  时间:2020/11/9 16:08:19  对本文有异议

单例设计模式实现

单例设计模式:某个类只能存在一个对象实例
设计要点:

  • 一个私有构造函数(不能外面new,只能自己创建)
  • 一个私有静态变量(确保只有一个实例)
  • 一个公共静态函数(调用,用来返回实例对象)

饿汉式

天生线程安全,用得也比较多
先创建实例,因为比较饿,没有延迟加载,如果很久没用到这个实例,就会浪费系统资源。

静态常量饿汉式

  1. public class Singleton {
  2. static class Singleton{
  3. private Singleton(){}
  4. private final static Singleton instance = new Singleton();
  5. public static Singleton getInstance() {
  6. return instance;
  7. }
  8. }
  9. }

静态代码块饿汉式

  1. public class Singleton {
  2. private Singleton() {
  3. }
  4. private static Singleton instance;
  5. static { // 在静态代码块中,创建单例对象
  6. instance = new Singleton();
  7. }
  8. public static Singleton getInstance() {
  9. return instance;
  10. }
  11. }

懒汉式

用的时候再创建实例,因为比较懒

线程不安全懒汉式

多线程下,一个线程进入了if判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。所以在多线程环境下不可使用这种方式

  1. public class Singleton {
  2. private static Singleton instance;
  3. private Singleton() {}
  4. //提供一个静态的公有方法,当使用到该方法时,才去创建实例
  5. public static Singleton getInstance() {
  6. if(instance == null) {
  7. instance = new Singleton();
  8. }
  9. return instance;
  10. }
  11. }

线程安全懒汉式

效率低,多线程时,每次都要进行上锁

  1. public class Singleton {
  2. private static Singleton instance;
  3. private Singleton() {}
  4. //加入同步处理的代码,解决线程安全问题
  5. public static synchronized Singleton getInstance() {
  6. if(instance == null) {
  7. instance = new Singleton();
  8. }
  9. return instance;
  10. }
  11. }

双重检测懒汉式(推荐)

线程安全,懒加载,效率较高

  1. class Singleton {
  2. private static volatile Singleton instance;
  3. private Singleton() {}
  4. public static Singleton getInstance() {
  5. if(instance == null) {
  6. synchronized (Singleton.class) {
  7. if(instance == null) {
  8. instance = new Singleton();
  9. }
  10. }
  11. }
  12. return instance;
  13. }
  14. }

volatile:保证了变量的可见性,如果发生改变,其他线程立马可见
双重检查:
首次创建实例时,进入第二个if判断后,还未创建实例,此时若有其他线程进来,通过了第一个if判断,然后因为有synchronized,被挡在了外面。
实例化代码只执行一次,后面线程再次访问时,在第一个if判断时,就直接return实例了。

静态内部类

线程安全,推荐使用
静态内部类方式在 Singleton 类被装载时并不会立即实例化,而是在需要实例化时,调用 getInstance 方法,才会装载 SingletonInstance 类,从而完成 Singleton 的实例化.
类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM 帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。
外部类被加载的时候,静态内部类不会被加载,静态代码块会被加载。

  1. public class Singleton {
  2. private static volatile Singleton instance;
  3. //构造器私有化
  4. private Singleton() {}
  5. //写一个静态内部类,该类中有一个静态属性 Singleton
  6. private static class SingletonInstance {
  7. private static final Singleton INSTANCE = new Singleton();
  8. }
  9. //提供一个静态的公有方法,直接返回
  10. SingletonInstance.INSTANCE
  11. public static Singleton getInstance() {
  12. return SingletonInstance.INSTANCE;
  13. }
  14. }

枚举

线程安全,还能防止反射和反序列化重新创建新的对象,不能延时加载

  1. enum Singleton {
  2. INSTANCE; //属性
  3. public void sayOK() {
  4. System.out.println("ok");
  5. }
  6. }

使用场景

需要频繁的进行创建和销毁的对象,比如:工具类对象,频繁访问数据库或文件对象。

JDK源码Runtime类

饿汉式单例
RunTime代表一个运行环境。每个JVM进程都是对应这一个Runtime实例,此实例是由JVM为其实例化的。每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。

  1. public class Runtime {
  2. private static Runtime currentRuntime = new Runtime();
  3. public static Runtime getRuntime() {
  4. return currentRuntime;
  5. }
  6. private Runtime() {}
  7. }

Spring依赖注入Bean实例

双重检查懒汉单例

  1. protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  2. Object singletonObject = this.singletonObjects.get(beanName);
  3. if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
  4. synchronized (this.singletonObjects) {
  5. singletonObject = this.earlySingletonObjects.get(beanName);
  6. if (singletonObject == null && allowEarlyReference) {
  7. ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
  8. if (singletonFactory != null) {
  9. singletonObject = singletonFactory.getObject();
  10. this.earlySingletonObjects.put(beanName, singletonObject);
  11. this.singletonFactories.remove(beanName);
  12. }
  13. }
  14. }
  15. }
  16. return (singletonObject != NULL_OBJECT ? singletonObject : null);
  17. }

SpringBoot源码中的单例

......

原文链接:http://www.cnblogs.com/potato20522/p/13796656.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号