单例模式引发相关整理

关联线程安全

在多线程下,懒汉式会有一定修改。当两个线程在if(null == instance)语句阻塞的时候,可能由两个线程进入创建实例,从而返回了两个对象。对此,我们可以加锁,保证仅有一个线程处于getInstance()方法中,从而保证了线程一致性。多线程下的单例

/**
* @author sunyang
* @date 2018/11/8 12:18
*/
public class Singleton4 { private static Singleton4 instance; private Singleton4(){ }
//需要加上synchronized 同步
public static synchronized Singleton4 getInstance(){
if (instance == null){
instance = new Singleton4();
}
return instance;
}
}

如果一个项目中有100次获取实例,那么jvm就会有100次进行加锁,释放锁的操作,每次操作都浪费资源。

可以在最外层再加一层判断,如下

/**
* @author sunyang
* @date 2018/11/12 19:07
*/
public class Singleton41 {
private static Singleton41 instance; private Singleton41(){} private static synchronized void doGetInstance(){
if (null == instance){
instance = new Singleton41();
}
} public static synchronized Singleton41 getInstance(){
if (null == instance){
doGetInstance();
}
return instance;
}
}

简化形式后:

/**
* @author sunyang
* @date 2018/11/12 19:13
*/
public class Singleton5 { private static Singleton5 instance; private Singleton5(){} //如果多个线程同时通过第一次检查,并且其中一个线程
// 首先通过了第二次检查并实例化了对象,那么剩余通过了
//第一次检查的线程就不会再去实例化对象。提升了效率
public static Singleton5 getInstance(){
if (null == instance){
synchronized (Singleton5.class){
if (null == instance){
instance = new Singleton5();
}
}
}
return instance;
}
}

题外话:一个类在new的时候,一般经历以下三个顺序:

1.开辟空间

2.符号引用改空间,并在空间内对类进行初始化操作

3.将符合引用转为直接引用这个时候if(null==instance) return false;


在实际的情况中,为了降低CPU的闲置时间,jvm会对指令进行重排序以形成指令流水线。顺序可能乱序:

1.开辟空间

2.转为直接引用

3.初始化类

结论:双重检查机制就会出现问题:可能返回一个未被完全初始化的类;

代码不安全截图

 
volatile单例中的作用
  • 可见性:jvm中每一个线程都有自己的内存区域。对变量使用volatile修饰,可以强制将每一次的读写都写入堆内存中,实现了各个线程都能共享的最新数据。
  • 禁止指令重排序优化:被volatile修饰的变量,在赋值的结尾会插入一个内存屏障,从而防止指令重排序。volatile增强了数据的一致性。
/**
* 解决上图双重检查机制出现的问题,可能返回一个未被完全初始化的类
*
* @author sunyang
* @date 2018/11/12 20:24
*/
public class Singleton51 { private static volatile Singleton51 instance; private Singleton51(){}
public static Singleton51 getInstance(){
if (null==instance){
synchronized (Singleton51.class){
if (null == instance){
instance = new Singleton51();
}
}
}
return instance;
}
}
如果实现懒加载

先了解下静态嵌套类的使用

静态嵌套类:是一种在类之外声明的嵌套类,由于是静态的,所以不经过初始化,就可以通过类名直接调用。

内部类:该类作为另一个类的成员,因此只有引用另一个类,才能创建这个类。通过静态嵌套类,便可以实现

对饿汉式进行懒化的效果。

/**
* @author sunyang
* @date 2018/11/12 20:42
*/
public class Singleton6 {
private Singleton6(){}
//静态内部类
private static class SingletonHolder{
private static Singleton6 INSTANCE = new Singleton6();
} //通过静态嵌套类,便可以实现对饿汉式进行懒化的效果
public static final Singleton6 getInstance(){
return SingletonHolder.INSTANCE;
}
}
分析

要分析这种方式有没有实现懒加载,就要分析一下语句new Singleton6()是什么时候被调用的.

使用javac进行编译,会得到如下图的三个class文件:

 

从图上可以看到,静态嵌套类是单独作为一个class存在,而其中创建对象的逻辑位于嵌套类中,jvm读取嵌套类的字节码以后才能创建对象,从硬盘中读取class文件,在内存中分配空间,是一件费事费力的工作,所以jvm选择按需加载,没有必要加载的就不加载,没必要分配就不分配。

Java设计模式 - 单例模式详解(下)的更多相关文章

  1. Java设计模式-单例模式详解(上)

    单例模式整理 敲了多年代码后,回头来看会别有一番滋味在心头.. 概念 单例模式是为了保证在一个jvm环境下,一个类仅有一个对象. 代码中常见的懒汉式.饿汉式,这些实现方式可以通过代码的设计来强制保证的 ...

  2. Java设计模式 - 单例模式详解(扩展)

    单例模式引发相关整理 如何破坏单例模式 示例: /** * 如果破坏单例模式 * * @author sunyang * @date 2018/11/13 20:14 */ public class ...

  3. 【转】Java设计模式-单例模式详解

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6510196.html 所谓单例,指的就是单实例,有且仅有一个类实例,这个单例不应该由人来控 ...

  4. java设计模式案例详解:工厂模式

    1.简单工厂模式 在不考虑扩展的情况下还是很好用的,其实我们写代码也很经常用到,其主要理解在于传入不同参数则构建不同对象,只有一个工厂,如需添加产品涉及到扩展需要修改比较多的东西,不符合开闭原则,如下 ...

  5. java设计模式案例详解:观察者模式

    观察者模式的应用场景: 1. 对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变. 2. 对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节. 举个例子说明,这个例子讲 ...

  6. Java设计模式----观察者模式详解

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/3 ...

  7. java设计模式案例详解:代理模式

    代理模式就是用一个第三者的身份去完成工作,其实际意义跟字面意思其实是一样的,理解方式有很多,还是例子直观. 本例的实现类是实现买票功能,实际应用想要添加身份验证功能,利用代理模式添加验证步骤.上例子: ...

  8. 9种Java单例模式详解(推荐)

    单例模式的特点 一个类只允许产生一个实例化对象. 单例类构造方法私有化,不允许外部创建对象. 单例类向外提供静态方法,调用方法返回内部创建的实例化对象.  懒汉式(线程不安全) 其主要表现在单例类在外 ...

  9. Mac下Intellij IDea发布Java Web项目详解五 开始测试

    测试前准备工作目录 Mac下Intellij IDea发布Web项目详解一 Mac下Intellij IDea发布Java Web项目(适合第一次配置Tomcat的家伙们)详解二 Mac下Intell ...

随机推荐

  1. 「ZJOI2019」&「十二省联考 2019」题解索引

    「ZJOI2019」&「十二省联考 2019」题解索引 「ZJOI2019」 「ZJOI2019」线段树 「ZJOI2019」Minimax 搜索 「十二省联考 2019」 「十二省联考 20 ...

  2. 给你的WordPress站点添加下雪特效

    今天看到这个教程,感觉挺应景的,就自己尝试了下,效果还行,没截GIF图 方法: 该js文件已支持https,同时已将其及相关雪花图片进行CDN加速处理,可直接调用. 找到WordPress主题的foo ...

  3. 吴恩达机器学习笔记13-正规方程(Normal Equation)

    到目前为止,我们都在使用梯度下降算法,但是对于某些线性回归问题,正规方程方法是更好的解决方案.如: 即: 运用正规方程方法求解参数: 注:对于那些不可逆的矩阵(通常是因为特征之间不独立,如同时包含英尺 ...

  4. Day6:html和css

    Day6:html和css 复习 margin: 0; padding: 0; <!DOCTYPE html> <html lang="en"> <h ...

  5. Golang之发送消息至kafka

    windows下安装zookeeper 1.安装JAVA-JDK,从oracle下载最新的SDK安装(我用的是1.8的) 2.安装zookeeper3.3.6,下载地址:http://apache.f ...

  6. new 操作符 做了什么

    new 操作符 做了什么 new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例. 假设Test是一个构造函数,通常在创建对象的实例时,要使用new,eg:test = new ...

  7. JavaScript百宝箱

    Js的外部引用 外部文件中不用添加<script>标签,引用书写位置需在使用之前 <script type="text/javascript" src=" ...

  8. spring boot -整合Ehcahe

    <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring- ...

  9. odoo开发笔记 -- tree视图按指定字段group_by分组显示

    注意点: view视图文件中的搜索视图要放在action视图的前边. 在action视图中,要写search_view_id, 还有context, search_default_group_by_字 ...

  10. 【shiro】(1)---了解权限管理

    了解权限管理 一.概念 1.什么是权限管理 只要有用户参与的系统一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源. 权限管理包 ...