Java单例实现及分析
双重检验锁实现方式
public class Singleton {
//定义一个私有的空构造方法,防止直接用new实例化
private Singleton() {}
private static volatile Singleton singleton = null;
public static Singleton getInstance() {
if(singleton == null) {
synchronized(Singleton.class) {
if(singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
双重校验锁,从代码的中可以看出,在同步代码块外多了一层instance为空的判断,由于单例对象只需要创建一次,如果后面再次调用getInstance()只需要直接返回单例对象即可,因此,在大部分情况下,调用getInstance()都不会执行到同步代码块,从而提高的程序性能。但是还需要考虑一种情况,假如两个线程A、B,线程A执行了if(instance == null)语句,它会任务单例对象没有创建,此时线程切到B也执行了同样的语句,B也认为单例对象没有创建,然后两个线程一次执行同步代码块,并分别创建了一个单例对象,所以为了解决这个问题,还需要在同步代码块中增加if(instance == null)的语句判断,避免重复创建的问题。
可以发现instance变量使用了volatile修饰,这样做的目的在于禁止指令重排序优化,所谓指令重排序优化是指在不改变原语义的前提下,通过调整指令的执行顺序让程序运行的更快,JVM中并没有规定编译器优化的相关内容,也就是说JVM可以自由的镜像指令重排序优化,这样会导致Singleton和将对象赋值给instance字段的顺序是不确定的。在摸个线程创建单例对象时,在构造方法被调用之前,就为该对象分配了内存空间将对象的字段设置为默认值。此时就可以将分配的内存地址赋值给instance字段了,然而该对象可能还没有初始化,若紧接着另一个线程来调用getInsatance,取到的就是状态不正确的对象,程序就会出错。volatile的一个语义是禁止指令重排序优化,也就是保证了instance遍历被赋值的时候对象已经是初始化过的,从而避免上面说的问题。
静态内部类实现方式
public class Singleton{
private static class SingletonHolder{
public static Singleton instance = new Singleton();
}
private Singleton(){}
public static Singleton newInstance(){
return SingletonHolder.instance;
}
}
这种方式同样利用了类加载机制来保证只创建一个instance实例。它与饿汉模式一样,也是利用了类加载机制,因此不存在多线程并发的问题。不一样的是,它是在内部类里面去创建对象实例。这样的话,只要应用中不使用内部类,JVM就不会去加载这个单例类,也就不会创建单例对象,从而实现懒汉式的延迟加载。也就是说这种方式可以同时保证延迟加载和线程安全。
Java单例实现及分析的更多相关文章
- java单例的几种实现方法
java单例的几种实现方法: 方式1: public class Something { private Something() {} private static class LazyHolder ...
- java单例类/
java单例类 一个类只能创建一个实例,那么这个类就是一个单例类 可以重写toString方法 输出想要输出的内容 可以重写equcal来比较想要比较的内容是否相等 对于final修饰的成员变量 一 ...
- java单例-积木系列
一步步知识点归纳吧,把以前似懂非懂,了解表面,知道点不知道面的知识归一下档. 懒汉式单例: 私有化构造函数,阻止外界实例话对象,调用getInstance静态方法,判断是否已经实例化. 为什么是懒 ...
- Java单例类的简单实现
对于java新手来说,单例类给我的印象挺深,之前一道web后台笔试题就是写单例类.*.*可惜当时不了解. 在大部分时候,我们将类的构造器定义成public访问权限,允许任何类自由创建该类的对象.但在某 ...
- 【Java学习笔记之三十】详解Java单例(Singleton)模式
概念: Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建 ...
- 转:java单例设计模式
本文转自:http://www.cnblogs.com/yinxiaoqiexuxing/p/5605338.html 单例设计模式 Singleton是一种创建型模式,指某个类采用Singleton ...
- 熟悉的味道——从Java单例写到C++单例
设计模式中,单例模式是常见的一种.单例模式需要满足以下两个条件: 保证一个类只能创建一个示例: 提供对该实例的全局访问点. 关于单例最经典的问题就是DCL(Double-Checked Lock),今 ...
- java单例五种实现模式梳理
java单例五种实现模式 饿汉式(线程安全,调用效率高,但是不能延时加载) 一上来就把单例对象创建出来了,要用的时候直接返回即可,这种可以说是单例模式中最简单的一种实现方式.但是问题也比较明显.单例在 ...
- JAVA单例实现方式(常用)
JAVA单例实现方式(常用) public class Singleton { // Q1:为什么要使用volatile关键字? private volatile static Singleton u ...
随机推荐
- Centos7 update dotnet 无法识别
使用了yum update 后 原来好好的dotnet 用不了了 /usr/bin/dotnet 找不到 卸载重装都没法了.... 解决方法: 把dotnet 拷贝到 /usr/bin 下面去就好了 ...
- JAVA课堂测试之查找字母和单词出现次数、频率
代码如下:没有加注释,自己研究吧. import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;i ...
- centos安装mariadb
一 配置mariadb官方的yum源 1.进入yum仓库 /etc/yum.repos.d/目录下 手动创建一个 mariadb.repo 写入如下内容 [mariadb] name = Maria ...
- [转载]URL 源码分析
URI 引用包括最多三个部分:模式.模式特定部分和片段标识符.一般为: 模式:模式特定部分:片段 如果省略模式,这个URI引用则是相对的.如果省略片段标识符,这个URI引用就是一个纯URI. URI是 ...
- python简单制作GIF
第一步安装工具:imageio (已安装好的页面) 第二步:打开python 插入代码,代码如下. import imageio savename = "C://Users//Thinkpa ...
- clean exit - waiting for changes before restart
在使用nodemon的时候,针对于同一个文件一次使用还好,当多次使用的时候就会出现这样的情况: 解决办法: nodemon clean exit 原因: 可能是因为缓存造成的:
- 删除zabbix数据库日志
#!/bin/bashuser="root"passwd="361way"timedate=`date -d $(date -d "-90 day&q ...
- linux启动httpd服务出现 Could not reliably determine the server`s fully qualified domain name.
安装好apache启动httpd服务时,出现httpd: Could not reliably determine the server's fully qualified domain name, ...
- MySQL 常用30种SQL查询语句优化方法
1.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描. 2.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉 ...
- 自动化测试系列:将常用的Android adb shell 命令行封装为C#静态函数
更多原创测试技术文章同步更新到微信公众号 :三国测,敬请扫码关注个人的微信号,感谢! 简介:adb命令是常用的Android命令行,自动化.代码调试.手工排查问题都会用的到,这里将常用的一些命令行封装 ...