Java 多线程(四)—— 单例模式
这篇博客介绍线程安全的应用——单例模式。
单例模式
单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。
双重校验锁
实例:
/**
* @author: ChenHao
* 关于懒汉式的线程安全问题,使用同步机制
* 对于一般的方法内,使用同步方法块,可以考虑使用this
* 对于静态方法而言,使用当前类充当锁。
*/
public class TestSingleton {
public static void main(String[] args) {
System.out.println(MySingle.getInstance());
System.out.println(MySingle.getInstance());
}
} class MySingle{
//声明一个私有的静态变量,第一次调用才初始化,避免内存浪费。
private volatile static MySingle instance=null;
//让构造器为private私有化,避免外部直接创建对象
private MySingle(){}
public static MySingle getInstance(){
if(null ==instance){//提高效率:如果已经存在对象,则不进行锁等待,直接返回对象,只有当对象为空才会进入锁等待,这里可以在第一个进入锁创建对象后,sleep10秒来放大效果
//这里有五个线程等待
synchronized(MySingle.class){
//第一次:当一个线程进来后,其他线程都在锁外面
//第一个线程创建对象后,释放锁,其他线程得到锁后,如果instance不为null,则不需要创建
if(null ==instance){
instance =new MySingle();
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
return instance;
}
}
代码分析:多个线程同时创建MySingle类的实例,比如现在有6个线程,第一次同时调用getInstance()静态方法,
线程A获取了锁,其他5个线程都在synchronized(MySingle.class)外面等待,第一个线程创建对象后,释放锁,其他线程得到锁后,如果instance不为null,则不需要创建;
第一个if(null ==instance)作用是提高效率:如果已经存在对象,则不进行锁等待,直接返回对象,只有当对象为空才会进入锁等待,这里可以在第一个进入锁创建对象后,sleep10秒来放大效果,此时已经创建了instance ,但是还没有释放锁,所以新来的线程不需要再等待锁,直接使用已经创建好的instance;
第二个if(null ==instance)判断instance是否已经存在,如果第一个线程已经创建instance,并释放锁,接下来的线程进入后则不需要再创建;
运行结果:输出相同的对象实例
饿汉
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
CAS(AtomicReference)实现单例模式
public class Singleton {
private static final AtomicReference<Singleton> INSTANCE = new AtomicReference<Singleton>(); private Singleton() {} public static Singleton getInstance() {
for (;;) {
Singleton singleton = INSTANCE.get();
if (null != singleton) {
return singleton;
} singleton = new Singleton();
if (INSTANCE.compareAndSet(null, singleton)) {
return singleton;
}
}
}
}
用CAS的好处在于不需要使用传统的锁机制来保证线程安全,CAS是一种基于忙等待的算法,依赖底层硬件的实现,相对于锁它没有线程切换和阻塞的额外消耗,可以支持较大的并行度。
CAS的一个重要缺点在于如果忙等待一直执行不成功(一直在死循环中),会对CPU造成较大的执行开销。而且,这种写法如果有多个线程同时执行singleton = new Singleton();也会比较浪费堆内存。
Java 多线程(四)—— 单例模式的更多相关文章
- java 多线程四
java 多线程一 java 多线程二 java 多线程三 java 多线程四 一个生产者,消费者的例子: import java.util.Stack; /** * Created by root ...
- java多线程(四)-自定义线程池
当我们使用 线程池的时候,可以使用 newCachedThreadPool()或者 newFixedThreadPool(int)等方法,其实我们深入到这些方法里面,就可以看到它们的是实现方式是这样的 ...
- java多线程与单例模式(Singleton)不得不说的故事
转发自:http://blog.csdn.net/ligang7560/article/details/50890282 单例模式的多种实现方式 我们都知道单例模式有几种常用的写法: - 饿汉模式 - ...
- Java多线程(四) 线程池
一个优秀的软件不会随意的创建.销毁线程,因为创建和销毁线程需要耗费大量的CPU时间以及需要和内存做出大量的交互.因此JDK5提出了使用线程池,让程序员把更多的精力放在业务逻辑上面,弱化对线程的开闭管理 ...
- java多线程四种实现模板
假设一个项目拥有三块独立代码块,需要执行,什么时候用多线程? 这些代码块某些时候需要同时运行,彼此独立,那么需要用到多线程操作更快... 这里把模板放在这里,需要用的时候寻找合适的来选用. 总体分为两 ...
- Java多线程(四) —— 线程并发库之Atomic
一.从原子操作开始 从相对简单的Atomic入手(java.util.concurrent是基于Queue的并发包,而Queue,很多情况下使用到了Atomic操作,因此首先从这里开始). 很多情况下 ...
- java多线程环境单例模式实现详解
Abstract 在开发中,如果某个实例的创建需要消耗很多系统资源,那么我们通常会使用惰性加载机制,也就是说只有当使用到这个实例的时候才会创建这个实例,这个好处在单例模式中得到了广泛应用.这个机制在s ...
- java 多线程,单例模式类(创建对象)最优写法
单例模式 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式涉及到一个单一的类,该类负责创 ...
- Java多线程之单例模式(线程安全)
package org.study2.javabase.ThreadsDemo.sync; /** * @Auther:GongXingRui * @Date:2018/9/20 * @Descrip ...
- java多线程(四)之同步机制
1.同步的前提 多个线程 多个线程使用的是同一个锁 2.同步的好处 同步的出现解决了多线程的安全问题 3.同步的弊端 当线程较多时, 因为每个线程都会去判断同步上的锁, 这样是很耗费资源的, 会降低程 ...
随机推荐
- ZOJ 3876 JAVA
题意: 输入年份,求五一假期一共放多少天假.五一假期默认5天,如果5月1号星期一,那么它之前有星期六星期天两天假期, 假期总长度就变成5+2,五一假期结束第二天也需要判断是不是假期. 思路: 使用Ja ...
- 磁共振成像SENSE 并行加速重建 g-factor计算方法(待更新)
MRI SENSE 并行图像加速重建 g-factor计算方法: Matlab代码如下: function g=gfactor_noise(map,LOSS,Rx,Ry) % map -> se ...
- myeclipse中的HTML页面在浏览器中显示为乱码
myeclipse中的HTML页面在浏览器中显示为乱码 在通过myeclipse开发项目的过程中,如果用HTML页面书写前端,可能出现中文乱码现象,需要怎么解决呢?下面是我从网上搜的方法: 解决办法: ...
- 记一次Dynamic Batching不生效的爬坑实例分析[Unity]
最近在项目开发过程中,无意发现游戏场景的绘制占用了大量的Batches,几乎一个模型显示就占用了一个Batch,而Saved by batching数量几乎为0,即没有任何合批渲染优化.这显然跟预期相 ...
- 服务器黑屏,只出现cmd窗口的解决办法
先上图,如图所示,正常启动或者进入安全模式都出现此现象,尝试了各种办法,比如: 1.打开此页面后,重新开一台可以远程的电脑连接,此方法不通: 2.进任务管理器无explorer.exe进程,且创建此进 ...
- Android进程间通信IPC
一.IPC的说明 IPC是Inter-Process Communication的缩写,含义为进程间通信或跨进程通信,是指两个进程之间进行数据交换的过程. IPC不是Android独有的,任何一个操作 ...
- android中Imageview的布局和使用
布局: <ImageView android:id="@+id/imt_photo" android:layout_width="fill_parent" ...
- js中的单例模式
1.场景:当我们需要多人合作完成一个项目,但是有一些操作是同样的操作时(例如:点击按钮显示加载的遮罩层:例如:提交表单时的验证都是一样的),这个时候我们就需要单例模式: 2.什么是单例模式:是一种常见 ...
- 电子科技大学实验中学PK赛(一)比赛题解
比赛来源:第十四届重庆大学程序设计大赛暨西南地区高校邀请赛现场初赛 比赛地址:http://qscoj.cn/contest/24/ A. Comb 自述 分析:统计ACM在题目描述中出现的次数,认真 ...
- 干货分享:Neutron的PPT,帮助你理解Neutron的各种细节
深入解析Neutron http://files.cnblogs.com/popsuper1982/Neutron.pptx 经典的三节点部署 架构 怎么理解? 更加深入:Tap Interface ...