关于多线程中单例模式的使用学习笔记
2017-06-24 20:17
337 查看
最近在学习设计模式中的单例模式,写下此篇总结,权当笔记。
单例模式是一种常见的设计模式。为了保持程序运行时jvm中单例对象只存在一个,这样的方式有这些优点:省去了繁多的new关键字的使用,节省了系统的开销,减轻了CG回收的压力,在有的系统中要求只能拥有一个实例,只有这样才能控制系统的核心逻辑不会错。
在使用单例模式时,可以使用如下例子的方法创建:
以上例子可以满足基本的要求,但是如果考虑多线程时,只有上述例子的措施还是不够的。试想在线程A使用getSingle方法创建实例时,线程B也运行到了getSingle这个方法,都判断sin为null,也就都会创建sin这个实例。这对于使用final修饰的sin对象来说,是不符合java的语法的。为解决这个问题,我们想到使用synchronized关键自实现线程互斥。现将getSingle方法改造如下:
使用关键字似乎可以完成期望,但是jvm在完成赋值和创建对象上是不同步的,也就是说在sin实例化的时候,jvm先申请了一个空内存,然后直接赋值给sin(这是jvm还没有对sin进行实例化)。这样sin就不null,线程B就不经过sin对象的实例化,但这是sin对象实际只是一个空的内存引用。这样线程B在后续的程序运行中就会出现问题。
其实比较完善且常使用的方式是这样的:
这个改进的例子原理是,在类加载时,加载过程中是线程互斥的。这样,就保证了实例过程中的线程互斥。
单例模式是一种常见的设计模式。为了保持程序运行时jvm中单例对象只存在一个,这样的方式有这些优点:省去了繁多的new关键字的使用,节省了系统的开销,减轻了CG回收的压力,在有的系统中要求只能拥有一个实例,只有这样才能控制系统的核心逻辑不会错。
在使用单例模式时,可以使用如下例子的方法创建:
public class Single{ //使用static 修饰类的实例 private static Single sin = null; //构造方法私有化,防止直接实例化 private Single(){} //创建静态方法,返回本类的实例 public static Single getSingle(){ if(sin==null){ sin = new Single(); } return sin; } }
以上例子可以满足基本的要求,但是如果考虑多线程时,只有上述例子的措施还是不够的。试想在线程A使用getSingle方法创建实例时,线程B也运行到了getSingle这个方法,都判断sin为null,也就都会创建sin这个实例。这对于使用final修饰的sin对象来说,是不符合java的语法的。为解决这个问题,我们想到使用synchronized关键自实现线程互斥。现将getSingle方法改造如下:
public static Single getSingle(){ synchronized(sin){ if(sin == null){ sin = new Single(); } } return sin; }
使用关键字似乎可以完成期望,但是jvm在完成赋值和创建对象上是不同步的,也就是说在sin实例化的时候,jvm先申请了一个空内存,然后直接赋值给sin(这是jvm还没有对sin进行实例化)。这样sin就不null,线程B就不经过sin对象的实例化,但这是sin对象实际只是一个空的内存引用。这样线程B在后续的程序运行中就会出现问题。
其实比较完善且常使用的方式是这样的:
public class Single{ private static class SingleFactory{ private static Single sin = new Single(); } public static getSingle(){ return SingleFactory.sin; } }
这个改进的例子原理是,在类加载时,加载过程中是线程互斥的。这样,就保证了实例过程中的线程互斥。
相关文章推荐
- python学习笔记4:多进程和多线程的使用方法和区别
- Java多线程学习笔记——信号量的使用
- python学习笔记之使用threading模块实现多线程(转)
- Java学习笔记(一)——JAVA中关于对象数组的定义与使用
- Silverlight学习笔记2:Silverlight中使用多线程实现倒计时
- Spring学习笔记 关于Spring创建Bean的模式-Singleton(单例模式)和Prototype
- React Native 学习笔记七(关于布局的使用)
- [C#学习笔记之多线程1]使用ParameterizedThreadStart委托向线程函数传送参数
- 学习java多线程的笔记3-使用BlockingQueue阻塞队列来模拟两个线程之间的通信
- Java消息中间件学习笔记五 -- ActiveMQ的使用【主题模式】
- JAVA并发设计模式学习笔记(一)—— JAVA多线程编程
- Android(java)学习笔记76:多线程-定时器概述和使用
- Java多线程学习笔记--生产消费者模式
- 【DAY9】关于多线程的学习笔记
- openGL学习笔记四 : 关于颜色, 大小, 虚线, 多边形反转, 镂空, 使用位图
- C#多线程学习笔记之(abort与join配合使用)
- Java6学习笔记60——多线程编程——使用volatile保障原子性
- Java学习笔记(二)——关于使用基础类的技巧
- Java 学习笔记23:关于Java Session使用
- ASP.NET学习笔记[2] - 关于使用Master.Page的几点注意事项