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 ...
随机推荐
- DataGridView修改HeaderText
dataGridView_htList为一个 DataGridView(ht为HoverTree的缩写)方法一:dataGridView_htList.Columns["HtAddTime& ...
- 用node-webkit(NW.js)创建桌面程序
以往写windows桌面程序需要用MFC.C#之类的技术,那么如果你只会web开发技术呢?或者说你有一个网站,但是你想把你的网站打包成一个桌面应用程序,该如何做呢? 答案就是用node-webkit这 ...
- java servlet+mysql全过程(原创)
前段时间写过一篇 servlet+oracle的文章,但是那是因为公司有可能接那么一个项目,然后我当时也比较闲,所以随便学了下,那玩意是白去研究了,因为公司后面并没接到那项目. 这次学servlet用 ...
- php中数组遍历改值
<?php $arr = array(100, 99, 88, 77, 55, 66); //方法1 foreach ($arr as &$v) { $v = 2; } print_r( ...
- [mysql] 查看mysql执行时间
mysql的 profiling不是默认打开的 查看profiling是否找开 mysql> show variables like "%pro%"; +---------- ...
- CentOS 6.5/6.6 安装(install)mysql 5.7 最完整版教程
Step1: 检测系统是否自带安装mysql # yum list installed | grep mysql Step2: 删除系统自带的mysql及其依赖命令: # yum -y remove ...
- HTML5的Server-Sent Events介绍
body{ font: 16px/1.5em 微软雅黑,arial,verdana,helvetica,sans-serif; } HTML5有一个Server-Sent Events(S ...
- Fiddler (四) 实现手机的抓包
Fiddler是我最喜爱的工具,几乎每天都用, 我已经用了8年了. 至今我也只学会其中大概50%的功能. Fiddler绝对称得上是"神器", 任何一个搞IT的人都得着的. 小 ...
- Nginx负载均衡配置实例详解
负载均衡是我们大流量网站要做的一个东西,下面我来给大家介绍在Nginx服务器上进行负载均衡配置方法,希望对有需要的同学有所帮助哦. 负载均衡 先来简单了解一下什么是负载均衡,单从字面上的意思来理解就可 ...
- C#的库存管理之旅的别样意义
我不知道大家对C#的一些基础知识掌握得怎么样了? 但无论怎么样,都应该静心下来去慢慢品味我的总结以及“库存管理”项目需用到的一些知识和技巧.你将会得到你料想不到的收获哦. 知识梳理: 数据类型:boo ...