java多线程与单例模式(Singleton)不得不说的故事
转发自:http://blog.csdn.net/ligang7560/article/details/50890282
单例模式的多种实现方式
我们都知道单例模式有几种常用的写法:
- 饿汉模式
- 懒汉模式
- 双重校验锁
- 静态内部类
- 静态代码块
我们来看一下这几种模式在多线程的场景中,能否保持单例
1.饿汉模式
public class HungrySingleton {
//立即加载模式
private static HungrySingleton hungrySingleton = new HungrySingleton();
private HungrySingleton(){}
public static HungrySingleton getInstance(){
return hungrySingleton;
}
}
接下来我们写一个线程类,再写一个测试类,来看下饿汉模式在多线程下的表现如何:
运行测试类结果如下:
546862187
546862187
546862187
这说明饿汉模式是线程安全,在多线程的情况下,也能够保持单例.
2.懒汉模式
public class LazySingleton {
private static LazySingleton lazySingleton;
private LazySingleton() {}
public static LazySingleton getInstance(){
if(lazySingleton!=null){
}else{
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
同样的我们来写一个线程类,写一个测试类;
运行结果:
2030251396
546862187
2030251396
我们看到对象返回的哈希值不一致了,这就说明他们已经不是同一个对象实例了,也就是说这种写法是线程不安全的,那么我们对它进行如下的改造:
public class LazySingleton {
private static LazySingleton lazySingleton;
private LazySingleton() {}
//整个方法加同步,效率低
synchronized public static LazySingleton getInstance(){
if(lazySingleton!=null){
}else{
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
我们给整个getInstance方法添加了个synchronized关键字,才保证多线程的情况下也能保持单例,我们再运行一下测试类:
1638084561
1638084561
1638084561
这时我们看见已经没有问题了,就是说写法是正确的,但是这种写法导致所以并发的线程获取实例时都是排队进行的,那么就会导致性能低下,接下来我们尝试另外一种写法,就是我们的第三种写法:双重校验锁.
3. 双重校验锁
public class LazySingleton {
private static LazySingleton lazySingleton;
private LazySingleton() {}
public static LazySingleton getInstance(){
if(lazySingleton!=null){
}else{
synchronized (LazySingleton.class){
if(lazySingleton==null){
lazySingleton = new LazySingleton();
}
}
}
return lazySingleton;
}
}
我们将排队进行的范围进行缩小,同时采用校验两次为空的方法,来保证单例模式的正确性,接下来我们来看一下测试结果:
2030251396
2030251396
2030251396
OK,没有问题.
4.静态内部类
public class StaticInnerClassSingleton {
//通过写一个静态的内部类来创建实例
private static class SingletonHandle{
private static StaticInnerClassSingleton singleton = new StaticInnerClassSingleton();
}
private StaticInnerClassSingleton(){}
public static StaticInnerClassSingleton getInstance(){
return SingletonHandle.singleton;
}
}
测试类和上面的都差不多,我就不贴图片了,直接看测试结果:
1523917841
1523917841
1523917841
没有问题,这种方式也是线程安全的,接下来我们看最后一种方式
5.静态代码块
public class StaticSingleton {
private static StaticSingleton staticSingleton=null;
private StaticSingleton(){};
static {
//通过静态代码块的执行,来获取实例
staticSingleton = new StaticSingleton();
}
public static StaticSingleton getInstance(){
return staticSingleton;
}
}
不废话了,直接看测试结果:
2030251396
2030251396
2030251396
没有问题,那么以上我们就介绍了5中关于多线程中单例模式的写法,其中呢就懒汉模式的一般写法容易造成错误,其他的写法都是线程安全的,文章中的代码我已经上传到github了,有需要的同学可以下载下来自己试试.
https://github.com/JokerLigang/Singleton.git
java多线程与单例模式(Singleton)不得不说的故事的更多相关文章
- java设计模式之 单例模式 Singleton
static 的应用 单例模式 Singleton 单例:保证一个类在系统中最多只创建一个实例. 好处:由于过多创建对象实例,会产生过多的系统垃圾,需要GC频繁回收,由于GC会占用较大的系统资源,所有 ...
- Java 设计模式(三)-单例模式(Singleton Pattern)
1 概念定义 1.1 定义 确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 1.2 类型 创建类模式 1.3 难点 1)多个虚拟机 当系统中的单例类被拷贝运行在多 ...
- java多线程环境单例模式实现详解
Abstract 在开发中,如果某个实例的创建需要消耗很多系统资源,那么我们通常会使用惰性加载机制,也就是说只有当使用到这个实例的时候才会创建这个实例,这个好处在单例模式中得到了广泛应用.这个机制在s ...
- Java设计模式之单例模式 - Singleton
用来创建独一无二的,是能有一个实例的对象的入场券.告诉你一个好消息,单例模式的类图可以说是所有模式的类图中最简单的,事实上,它的类图上只有一个类!但是,可不要兴奋过头,尽管从类设计的视角来说很简单,但 ...
- Java 基础:单例模式 Singleton Pattern
1.简介 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式涉及到一个单一的类,该类负责创 ...
- java 多线程,单例模式类(创建对象)最优写法
单例模式 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式涉及到一个单一的类,该类负责创 ...
- Java多线程之单例模式(线程安全)
package org.study2.javabase.ThreadsDemo.sync; /** * @Auther:GongXingRui * @Date:2018/9/20 * @Descrip ...
- Java多线程核心技术(五)单例模式与多线程
本文只需要考虑一件事:如何使单例模式遇到多线程是安全的.正确的 1.立即加载 / "饿汉模式" 什么是立即加载?立即加载就是使用类的时候已经将对象创建完毕,常见的实现办法就是直接 ...
- 创建模式--单例模式Singleton(JAVA)
创建模式之单例模式 在面试时经常会有人问单例模式,单例模式是在整个系统运行中仅且仅有一个实例,在被调用.我们熟知的Calendar就是这种, Calendar.newIns ...
随机推荐
- WinForm小白的WPF初试一:从PropertyGrid控件,输出内容到Word(上)
学WinForm也就半年,然后转到WPF,还在熟悉中.最近拿到一个任务:从PropertyGrid控件,输出内容到Word.难点有: 一.PropertyGrid控件是WinForm控件,在WPF中并 ...
- 在ListActivity中显示图标
在ListActivity中显示图标,好像并不复杂,实现起来却不轻松. 首先,定义列表中的每一行,这里不是用xml文件定义,而是用一个类定义,CheckBox.ImageView.TextView等控 ...
- Malformed \uxxxx encoding解决方法
java.lang.IllegalArgumentException: Malformed \uxxxx encoding. at java.util.Properties.loadConvert(U ...
- [范例] Firemonkey 弹簧动画
弹簧动画效果: 不用写任何代码,只需设定下面动画属性: 参考动画曲线: http://monkeystyler.com/guide/Interpolation-and-AnimationType-Il ...
- Java集合框架之List接口
在上一篇Java集合框架之Collection接口中我们知道List接口是Collection接口的子接口,List接口对Collection进行了简单的扩充,List接口中的元素的特点为有序,可重复 ...
- Android总结篇系列:Android广播机制
1.Android广播机制概述 Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的就是广播接收者(广播接收器).广播作为Android组件间的通 ...
- get传递中文产生乱码的解决方式汇总
1 最基本的乱码问题. 这个乱码问题是最简单的乱码问题.一般新会出现.就是页面编码不一致导致的乱码. <%@ page language="java" pageEncodin ...
- ArcGIS Server 开发实践之【Search类】
开发中整理的.不足之处还请谅解! ----------------------------------------------- Class:Search 调用方式:require(["es ...
- CSS3 使用自定义字体
CSS3 @font-face 规则 在 CSS3 之前,web 设计师必须使用已在用户计算机上安装好的字体.通过 CSS3,web 设计师可以使用他们喜欢的任意字体.当您您找到或购买到希望使用的字体 ...
- JavaScript 数据类型判断
JavaScript 的数据类型分为两类:原始类型(基本类型)和对象类型(引用类型).原始类型包括数字.字符串和布尔值,另外有两个特殊的原始值:null 和 undefined,除此之外的都是对象.对 ...