博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
几种单例模式的实现
阅读量:5958 次
发布时间:2019-06-19

本文共 2638 字,大约阅读时间需要 8 分钟。

hot3.png

1.饿汉式

public class Singleton        {            private static Singleton instance = new Singleton();            private Singleton(){                …            }            public static Singleton getInstance(){                     return instance;             }        }

缺点:第一次加载类的时候会连带着创建Singleton实例,这样的结果与我们所期望的不同,因为创建实例的时候可能并不是我们需要这个实例的时候。同时如果这个Singleton实例的创建非常消耗系统资源,而应用始终都没有使用Singleton实例,那么创建Singleton消耗的系统资源就被白白浪费了。

 

2.懒汉式

public class Singleton{            private static Singleton instance = null;            private Singleton(){                …            }            public static Singleton getInstance(){                if (instance == null)                    instance = new Singleton();                         return instance;             }        }

缺点:存在多线程并发问题,并发下可能创建多个对象。

3.解决并发问题

方法上使用Class锁机制

public static synchronized Singleton getInstance(){            if (instance == null)            instance = new Singleton();             return instance;         }

缺点:加载方法上锁粒度太大,影响并发。实际上当单例实例被创建以后,其后的请求没有必要再使用互斥机制了。

用double-checked locking将锁缩减至代码块级别

public static Singleton getInstance(){            if (instance == null)                synchronized(instance){                    if(instance == null)                        instance = new Singleton();                }            return instance;         }

 对于JVM而言,它执行的是一个个Java指令。在Java指令中创建对象和赋值操作是分开进行的,也就是说instance = new Singleton();语句是分两步执行的。但是JVM并不保证这两个操作的先后顺序,也就是说有可能JVM会为新的Singleton实例分配空间,然后直接赋值给instance成员,然后再去初始化这个Singleton实例。这样就使出错成为了可能。

使用volatile防止重排序:

public class Singleton{            private static volatile Singleton instance = null;            private Singleton(){ … }            public static Singleton getInstance(){        if (instance == null)             synchronized(instance){                 if(instance == null)                     instance = new Singleton();    }    return instance;      }

 

不加锁:为了实现慢加载,并且不希望每次调用getInstance时都必须互斥执行。

public class Singleton{            private Singleton(){                …            }            private static class SingletonContainer{                private static Singleton instance = new Singleton();            }            public static Singleton getInstance(){                return SingletonContainer.instance;            }        }

JVM内部的机制能够保证当一个类被加载的时候,这个类的加载过程是线程互斥的。这样当我们第一次调用getInstance的时候,JVM能够帮我们保证instance只被创建一次,并且会保证把赋值给instance的内存初始化完毕,这样我们就不用担心3.2中的问题。此外该方法也只会在第一次调用的时候使用互斥机制,这样就解决了3.1中的低效问题。最后instance是在第一次加载SingletonContainer类时被创建的,而SingletonContainer类则在调用getInstance方法的时候才会被加载,因此也实现了惰性加载。

 

https://www.cnblogs.com/jingpeipei/p/5771716.html

转载于:https://my.oschina.net/u/3705388/blog/1612891

你可能感兴趣的文章
利用单壁路由实现vlan间路由
查看>>
hello world
查看>>
CentOS 7 配置yum本地base源和阿里云epel源
查看>>
python 学习导图
查看>>
生成树
查看>>
(MYSQL) Unknown table 'a' in MULTI DELETE的解决办法
查看>>
作为一个程序员必备的素质
查看>>
Webpack入门教程十四
查看>>
HDU - 3564 Another LIS(LIS+线段树)
查看>>
深入浅出JavaScript (五) 详解Document.write()方法
查看>>
hibernate简单入门教程(四)---------关联映射
查看>>
去 IOE,MySQL 完胜 PostgreSQL
查看>>
++i 和 i++ 性能上的区别
查看>>
Mysql运维管理-一主多从宕机从库切换主库继续和从库同步过程16
查看>>
Tomcat优化之配置NIO运行模式
查看>>
用XSLT和XML改进Struts
查看>>
WEB测试—功能测试
查看>>
在react或vue中,for循环用Index作为key值是好还是坏呢?
查看>>
2014.10.1 Form中显示pdf文件
查看>>
NERDTree 快捷键辑录
查看>>