深入Java单例模式【转载】
private static final SingletonClass instance = new SingletonClass();
public static SingletonClass getInstance() {
return instance;
}
private SingletonClass() {
}
}
private static SingletonClass instance = null;
public static SingletonClass getInstance() {
if(instance == null) {
instance = new SingletonClass();
}
return instance;
}
private SingletonClass() {
}
}
null,然后就新建一个对象,返回出去;第二次再使用的时候,因为这个instance是static的,所以已经不是null了,因此不会再创建对
象,直接将其返回。
的,于是它开始创建实例,就在这个时候,CPU发生时间片切换,线程B开始执行,它要使用SingletonClass,调用getInstance()
方法,同样检测到instance是null——注意,这是在A检测完之后切换的,也就是说A并没有来得及创建对象——因此B开始创建。B创建完成后,切
换到A继续执行,因为它已经检测完了,所以A不会再检测一遍,它会直接创建对象。这样,线程A和B各自拥有一个SingletonClass的对象——单
例失败!
private static SingletonClass instance = null;
public synchronized static SingletonClass getInstance() {
if(instance == null) {
instance = new SingletonClass();
}
return instance;
}
private SingletonClass() {
}
}
loaded的那种情形的原因。原因就是检测null的操作和创建对象的操作分离了。如果这两个操作能够原子地进行,那么单例就已经保证了。于是,我们开
始修改代码:
private static SingletonClass instance = null;
public static SingletonClass getInstance() {
synchronized (SingletonClass.class) {
if(instance == null) {
instance = new SingletonClass();
}
}
return instance;
}
private SingletonClass() {
}
}
private static SingletonClass instance = null;
public static SingletonClass getInstance() {
if (instance == null) {
synchronized (SingletonClass.class) {
if (instance == null) {
instance = new SingletonClass();
}
}
}
return instance;
}
private SingletonClass() {
}
}
器代码,而是虚拟机代码。编译原理里面有一个很重要的内容是编译器优化。所谓编译器优化是指,在不改变原来语义的情况下,通过调整语句顺序,来让程序运行
的更快。这个过程成为reorder。
谁在前谁在后呢?JVM规范并没有规定。那么就存在这么一种情况,JVM是先开辟出一块内存,然后把指针指向这块内存,最后调用构造方法进行初始化。
instance是否为null。按照我们上面所说的内存模型,A已经把instance指向了那块内存,只是还没有调用构造方法,因此B检测到
instance不为null,于是直接把instance返回了——问题出现了,尽管instance不为null,但它并没有构造完成,就像一套房子
已经给了你钥匙,但你并不能住进去,因为里面还没有收拾。此时,如果B在A将instance构造完成之前就是用了这个实例,程序就会出现错误了!
private static SingletonClass instance = null;
public static SingletonClass getInstance() {
if (instance == null) {
SingletonClass sc;
synchronized (SingletonClass.class) {
sc = instance;
if (sc == null) {
synchronized (SingletonClass.class) {
if(sc == null) {
sc = new SingletonClass();
}
}
instance = sc;
}
}
}
return instance;
}
private SingletonClass() {
}
}
种代码基于以下思想,即synchronized会起到一个代码屏蔽的作用,同步块里面的代码和外部的代码没有联系。因此,在外部的同步块里面对临时变量
sc进行操作并不影响instance,所以外部类在instance=sc;之前检测instance的时候,结果instance依然是null。
5之后,Java使用了新的内存模型。volatile关键字有了明确的语义——在JDK1.5之前,volatile是个关键字,但是并没有明确的规定
其用途——被volatile修饰的写变量不能和之前的读写代码调整,读变量不能和之后的读写代码调整!因此,只要我们简单的把instance加上
volatile关键字就可以了。
private volatile static SingletonClass instance = null;
public static SingletonClass getInstance() {
if (instance == null) {
synchronized (SingletonClass.class) {
if(instance == null) {
instance = new SingletonClass();
}
}
}
return instance;
}
private SingletonClass() {
}
}
private static class SingletonClassInstance {
private static final SingletonClass instance = new SingletonClass();
}
public static SingletonClass getInstance() {
return SingletonClassInstance.instance;
}
private SingletonClass() {
}
}
为SingletonClass没有static的属性,因此并不会被初始化。直到调用getInstance()的时候,会首先加载
SingletonClassInstance类,这个类有一个static的SingletonClass实例,因此需要调用
SingletonClass的构造方法,然后getInstance()将把这个内部类的instance返回给使用者。由于这个instance是
static的,因此并不会构造多次。
在。并且,JSL规范定义,类的构造必须是原子性的,非并发的,因此不需要加同步块。同样,由于这个构造是并发的,所以getInstance()也并不
需要加同步。
本文出自 “豆子空间” 博客,请务必保留此出处http://devbean.blog.51cto.com/448512/203501
深入Java单例模式【转载】的更多相关文章
- Java 序列化 序列化与单例模式 [ 转载 ]
Java 序列化 序列化与单例模式 [ 转载 ] @author Hollis 本文将通过实例+阅读Java源码的方式介绍序列化是如何破坏单例模式的,以及如何避免序列化对单例的破坏. 单例模式,是设计 ...
- 用java单例模式实现面板切换
1.首先介绍一下什么是单例模式: java单例模式是一种常见的设计模式,那么我们先看看懒汉模式: public class Singleton_ { //设为私有方法,防止被外部类引用或实例 priv ...
- 如何用javac 和java 编译运行整个Java工程 (转载)【转】在Linux下编译与执行Java程序
如何用javac 和java 编译运行整个Java工程 (转载) http://blog.csdn.net/huagong_adu/article/details/6929817 [转]在Linux ...
- 【深入】java 单例模式(转)
[深入]java 单例模式 关于单例模式的文章,其实网上早就已经泛滥了.但一个小小的单例,里面却是有着许多的变化.网上的文章大多也是提到了其中的一个或几个点,很少有比较全面且脉络清晰的文章,于是,我便 ...
- 深入Java单例模式(转)
深入Java单例模式 源自 http://devbean.blog.51cto.com/448512/203501 在GoF的23种设计模式中,单例模式是比较简单的一种.然而,有时候越是简单的东西越容 ...
- Java 单例模式的七种写法
Java 单例模式的七种写法 第一种(懒汉,线程不安全) public class Singleton { private static Singleton instance; private Sin ...
- java单例模式之懒汉式分析
转自:http://blog.csdn.net/withiter/article/details/8140338 今天中午闲着没事,就随便写点关于Java单例模式的.其实单例模式实现有很多方法,这里我 ...
- Java 单例模式探讨
以下是我再次研究单例(Java 单例模式缺点)时在网上收集的资料,相信你们看完就对单例完全掌握了 Java单例模式应该是看起来以及用起来简单的一种设计模式,但是就实现方式以及原理来说,也并不浅显哦. ...
- 单例模式:Java单例模式的几种写法及它们的优缺点
总结下Java单例模式的几种写法: 1. 饿汉式 public class Singleton { private static Singleton instance = new Singleton( ...
- 9种Java单例模式详解(推荐)
单例模式的特点 一个类只允许产生一个实例化对象. 单例类构造方法私有化,不允许外部创建对象. 单例类向外提供静态方法,调用方法返回内部创建的实例化对象. 懒汉式(线程不安全) 其主要表现在单例类在外 ...
随机推荐
- 5.Android之image控件学习
Android中经常用到图片,比如图片浏览.图标等等,今天学习下image控件,image控件主要有ImageButton和ImageView两种. (1)ImageButton 在布局文件增加: & ...
- 【poj3159】 Candies
http://poj.org/problem?id=3159 (题目链接) 题意 有n个小朋友,班长要给每个小朋友发糖果.m种限制条件,小朋友A不允许小朋友B比自己多C个糖果.问第n个小朋友最多比第1 ...
- codevs3243 区间翻转
题目描述 Description 给出N个数,要求做M次区间翻转(如1 2 3 4变成4 3 2 1),求出最后的序列 输入描述 Input Description 第一行一个数N,下一行N个数表示原 ...
- Codeforces 85D Sum of Medians
传送门 D. Sum of Medians time limit per test 3 seconds memory limit per test 256 megabytes input standa ...
- POJ2392Space Elevator(贪心+背包)
Space Elevator Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9970 Accepted: 4738 De ...
- POJ1860Currency Exchange(Bellman + 正权回路)
Currency Exchange Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 23938 Accepted: 867 ...
- include(thinkphp常用内置标签)
变量输出使用普通标签就足够了,但是要完成其他的控制.循环和判断功能,就需要借助模板引擎的标签库功能了,系统内置标签库的所有标签无需引入标签库即可直接使用. XML标签有两种,包括闭合标签和开放标签,一 ...
- MySql开启事务
CREATE PROCEDURE test_sp1( ) BEGIN ; ; START TRANSACTION; INSERT INTO test VALUES(NULL, 'test sql 00 ...
- SOA面向服务架构简述
在上篇中我们简单谈了下架构设计中服务层的简单理解,在这里我们将继续服务层的架构,在本节我们将重点在于分布式服务.在分布式系统中表现层和业务逻辑层 并不处于同一物理部署,所以我们必须存在分布式服务,以契 ...
- iOS多线程介绍
一.线程概述 有些程序是一条直线,起点到终点:有些程序是一个圆,不断循环,直到将它切断.直线的如简单的Hello World,运行打印完,它的生命周期便结束了,像昙花一现那样:圆如操作系统,一直运行直 ...