预加载模式

代码:

public class Singleton
{
    private volatile static Singleton singleton = new Singleton();
    private Singleton()  {    }
    public static Singleton getInstance()   {
        return singleton;
    }
}

分析:

这种方式是预先加载单例,适合于单例对象初始化非常快,而且占用内存非常小,而且使用频繁的时候。

对于单例初始化的操作耗时比较长而应用对于启动速度又有要求,或者单例的占用内存比较大,再或者单例只是在某个特定场景的情况下才会被使用,需要延迟加载提高性能

volatile关键字作用

1.这个变量不会在多个线程中存在复本,直接从内存读取。

2.这个关键字会禁止指令重排序优化。也就是说,在 volatile 变量的赋值操作后面会有一个内存屏障(生成的汇编代码上),读操作不会被重排序到内存屏障之前。

双重检验锁方式

代码

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

singleton = new Singleton()这句,这并非是一个原子操作

事实上在 JVM 中这句话大概做了下面 3 件事情。

1.给 singleton 分配内存

2.调用 Singleton 的构造函数来初始化成员变量,形成实例

3.将singleton对象指向分配的内存空间(执行完这步 singleton才是非 null 了)

但是在 JVM 的即时编译器中存在指令重排序的优化。也就是说上面的第二步和第三步的顺序是不能保证的,最终的执行顺序可能是 1-2-3 也可能是 1-3-2。如果是后者,则在 3 执行完毕、2 未执行之前,被线程二抢占了,这时 instance 已经是非 null 了(但却没有初始化),所以线程二会直接返回 instance,然后使用,然后顺理成章地报错。

volatile关键字作用

1.这个变量不会在多个线程中存在复本,直接从内存读取。

2.这个关键字会禁止指令重排序优化。也就是说,在 volatile 变量的赋值操作后面会有一个内存屏障(生成的汇编代码上),读操作不会被重排序到内存屏障之前。

内部类方式(优雅)

代码

public class Singleton {
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    private Singleton (){}
    public static final Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

分析

老版《Effective Java》中推荐的方式

利用JVM的类加载机制去实现。在很多情况下JVM已经为我们提供了同步控制,比如:

在static{}区块中初始化的数据

访问final字段时

等等

因为在JVM进行类加载的时候他会保证数据是同步的

枚举:(优雅的我快那啥了。。。)

代码

public enum Singleton{
   INSTANCE;
}

分析

新版effective java推荐,非常优雅

使用方式

Singleton singleton = Singleton.INSTANCE;

本文参考了如下两篇博客

http://mp.weixin.qq.com/s?__biz=MzA4NTQwNDcyMA==&mid=403126596&idx=1&sn=101c6d4e363213bcdbe1879edeb08736#wechat_redirect

http://blog.csdn.net/haoel/article/details/4028232

欢迎入群:

公众号IT面试题汇总讨论群

如果扫描不进去,加我微信(rdst6029930)拉你。

扫我微信二维码加我

欢迎关注《IT面试题汇总》微信订阅号。每天推送经典面试题和面试心得技巧,都是干货!

微信订阅号二维码如下:

【14】-java的单例设计模式详解的更多相关文章

  1. java的单例设计模式

    java的单例设计模式包括:饿汉设计模式和懒汉设计模式: 步骤: 1.创建一个对象把他设置为私有的成员变量,保证唯一 2.私有构造方法,防止new一个对象. 3.定义一个公开的静态方法,返回第一步创建 ...

  2. Java中如果把构造方法也私有化,如何创建对象?Java的单例设计模式——饿汉式和懒汉式区别

    Java的单例模式——饿汉式 package com.swift; //Java单例设计模式——恶汉式 public class SinglePerson { private String name= ...

  3. 【设计模式】Java之单例设计模式

    1.单例设计模式:一个类只能有一个对象 1.1 创建单例类的步骤: 1.将构造方法私有化 2.创建私有的静态成员变量 3.共有的静态成员方法,提供当前的唯一对象 1.1 创建单例的两种方式: 1.饿汉 ...

  4. Java 之单例设计模式

    设计模式: 对问题行之有效的解决方式, 其实它是一种思想. 单例设计模式 解决的问题:就是可以保证一个类在内存中的对象唯一性. 即单个实例. 比如对于A 和 B 两个程序使用同一个配置信息对象时, A ...

  5. java singleton(单例设计模式)

    单例设计模式的主要作用是: 1.控制资源的使用,我们对资源使用线程同步来实现并发访问. 2.节约资源,我们对一个类只进行一个实例化进行全局的资源访问,节约了内存. 3.作为通信媒介,也是数据共享,可以 ...

  6. 【Java】单例设计模式

    文章目录 单例设计模式 什么是设计模式 单例设计模式 实现 饿汉式 懒汉式 饿汉式与懒汉式的区别 饿汉式 懒汉式 单例模式的应用场景 单例设计模式 什么是设计模式 设计模式是在大量的实践中总结和理论化 ...

  7. Java中的懒汉式单例与饿汉式单例实例详解

    懒汉式单例:线程非安全,当被调用的时候才创建实例,效率较高 public class LazySingleton { private static LazySingleton lazySingleto ...

  8. JAVA:23种设计模式详解(转)

    设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

  9. java之单例设计模式

    什么是设计模式? 设计模式是在大量的实践中总结和理论化之后优选的代码结构.编程风格.以及解决问题的思考方式.设计模式就像是经典的棋谱,不同的棋局,我们用不同的棋谱,免去我们自己再思考和探索. 所谓单例 ...

随机推荐

  1. Android简易实战教程--第二十五话《网络图片查看器》

    访问网络已经有了很成熟的框架.这一篇只是介绍一下HttpURLConnection的简单用法,以及里面的"注意点".这一篇可以复习或者学习HttpURLConnection.han ...

  2. Android-MVVM架构-Data Binding的使用

    项目整体效果: Awesome-Android-MVVM 什么是MVVM, 为什么需要 MVVM? 如何在Android中使用Data Binding实现MVVM架构? 什么是MVVM , 为什么需要 ...

  3. 携程React Native实践

    React Native(下文简称 RN)开源已经一年多时间,国内各大互联网公司都在使用,携程也在今年 5 月份投入资源开始引入,并推广给多个业务团队使用,本文将会分享我们遇到的一些问题以及我们的优化 ...

  4. Github Pages 搭建HEXO主题个人博客

    跌跌撞撞,总算是建立起来了.回首走过的这么多坑,也真的是蛮不容易的.那么就写点东西,记录我是怎么搭建的吧. 准备工作 安装Node.js: 用于生成静态页面,我们需要到官网上去下载即可.http:// ...

  5. Android存储之SharedPreferences

    Android数据存储之SharedPreferences SharedPreferences对象初始化 SharedPreferences mSharedPreferences = getShare ...

  6. API创建/更新员工薪水

    DECLARE lb_inv_next_sal_date_warning BOOLEAN; lb_proposed_salary_warning BOOLEAN; lb_approved_warnin ...

  7. 通过邮件找回密码功能的Java实现

    1.有个需求就是,忘记密码后通过邮箱找回.现在的系统在注册的时候都会强制输入邮箱,其一目的就是 通过邮件绑定找回,可以进行密码找回.通过java发送邮件的功能我就不说了,重点讲找回密码. 2.参考别人 ...

  8. Activity, Service,Task, Process and Thread之间的关系

    Activity, Service,Task, Process and Thread之间到底是什么关系呢? 首先我们来看下Task的定义,Google是这样定义Task的:a task is what ...

  9. ROS_Kinetic_17 使用V-Rep3.3.1(vrep_ros_bridge)

    ROS_Kinetic_17 使用V-Rep3.3.1(vrep_ros_bridge) https://github.com/lagadic/vrep_ros_bridge v-rep也有官网也有教 ...

  10. 分布式进阶(八)Linux提示Unable to locate package该如何处理?

    Linux提示Unable to locate package该如何处理? 当你在修改Linux软件源的时候,提示Unable to locate package错误,这是由什么原因导致的呢?又该如何 ...