设计模式学习--Singleton
What
Singleton:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
Why
Singletion是我比较熟悉的设计模式之一,在平常的开发过程中,也曾几次用到,它主要适用于如下场景:
1、当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
2、当这个唯一实例应该是通过子类可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。
在系统设计中,在涉及系统资源的管理时,往往会被设计成Singletion模式,比如缓存、日志对象、线程池、对话框等等。
How
假设如下场景:一个简单的线程池,需要实现增加线程以及获取单个线程的功能。显然这个线程池对象是一个Singletion对象。
简单的实现代码如下:
public class ThreadPool {
private List<Runnable> threads=new ArrayList<Runnable>();
private static ThreadPool threadPool=null;
private ThreadPool(){
}
public static ThreadPool getInstance(){
if(threadPool==null){
threadPool=new ThreadPool();
}
return threadPool;
}
public void add(Runnable thread){
System.out.append("add a thread!");
threads.add(thread);
}
}
客户端调用
ThreadPool threadPool=ThreadPool.getInstance();
threadPool.add(new Thread());
以上代码类图如下:
Discuss
线程安全的Singleton实现
以上代码,实现的是一个学习意义上的版本,在实际生产中,在一些情况下会出现问题,在多线程情况下,如下代码会出现什么问题?
public static ThreadPool getInstance(){
if(threadPool==null){
threadPool=new ThreadPool();
}
return threadPool;
}
在多线程条件下,当一个线程执行到new ThreadPool()但是还没返回给threadPool,这时thread=null,另一个线程也会进入if代码片段,这样就创建了两个threadPool,造成这个的原因就是这段代码是线程非安全的。
经过优化形成如下版本:
public static ThreadPool getInstance() {
synchronized (ThreadPool.class) {
if (threadPool == null) {
threadPool = new ThreadPool();
}
}
return threadPool;
}
这个版本可以很好的解决上个版本的问题,在一个线程进入了synchronized代码块,另一个线程就会等待。但是仔细想想,如果对象已经创建,线程还是需要等待进入synchronized代码块才会知道threadPool!=null,这样会造成比较严重性能问题,再来一个版本
public static ThreadPool getInstance() {
if (threadPool == null) {
synchronized (ThreadPool.class) {
if (threadPool == null) {
threadPool = new ThreadPool();
}
}
}
return threadPool;
}
ok,这个版本看上去完美了,可以在生产中使用了。这是线程安全的实现。
以上代码还是可以通过一些办法在一个JVM中创建多个ThreadPool实例,想想是什么?对,可以通过反射的方式来,创建n多个实例,java的反射机制可以通过private的构造器创建实例。
使用枚举实现Singleton
Effectvie java的作者Joshua Bloch提出了一个可以绝对防止多次实例化,而且无偿的提供了序列化机制的方法,使用枚举实现Singleton,当然java版本需要在1.5以上,下面是以上示例的使用枚举的实现
public enum ThreadPool {
Instance;
private List<Runnable> threads=new ArrayList<Runnable>();
public void add(Runnable thread){
System.out.append("add a thread!");
threads.add(thread);
}
}
客户端调用
ThreadPool.Instance.add(new Thread());
可以看出使用枚举方式,代码比较简洁而且可以绝对防止多次实例化,是一个实现Singleton的非常好的方法。
设计模式学习--Singleton的更多相关文章
- python之路,Day24 常用设计模式学习
python之路,Day24 常用设计模式学习 本节内容 设计模式介绍 设计模式分类 设计模式6大原则 1.设计模式介绍 设计模式(Design Patterns) --可复用面向对象软件的基础 ...
- Java设计模式学习记录-GoF设计模式概述
前言 最近要开始学习设计模式了,以前是偶尔会看看设计模式的书或是在网上翻到了某种设计模式,就顺便看看,也没有仔细的学习过.前段时间看完了JVM的知识,然后就想着JVM那么费劲的东西都看完了,说明自己学 ...
- C#设计模式学习笔记-单例模式随笔
最近学习 设计模式,从单例模式入手 啥是单例模式: 要实现一个单例类的话,首先,肯定是不能让用户自行生产的,那就是说明不能让用户new,所以,就必须把构造函数设置成为私有的 因为静态变量的生命周期跟整 ...
- C#设计模式学习笔记-单例模式(转)
C#设计模式学习笔记-单例模式 http://www.cnblogs.com/xun126/archive/2011/03/09/1970807.html 最近在学设计模式,学到创建型模式的时候,碰到 ...
- C#大话设计模式学习总结
如有雷同,不胜荣欣,如转载,请注明 C#大话设计模式学习总结 一.工厂模式 面向对象的三个特性:封装,继承和多态 1.封装 Class Operate { privatedouble _numberA ...
- Java设计模式学习笔记(五) 单例模式
前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 1. 使用单例模式的原因 以Windows任务管理器为例,在Windows系统中,任务管理器是唯 ...
- 设计模式学习系列6 原型模式(prototype)
原型模式(prototype)用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.允许一个对象再创建另外一个新对象的时候根本无需知道任何创建细节,只需要请求圆形对象的copy函数皆可. 1 ...
- Java-马士兵设计模式学习笔记-总结
<马士兵设计模式学习>学习了以下模式: 1.装饰者模式(例子:水管工,木工) 2.策略模式(例子:老师用职称比大小.学生用成绩比大小) 3.简单工厂模式(例子:VechileFactory ...
- Java设计模式学习资源汇总
本文记录了Java设计模式学习书籍.教程资源.此分享会持续更新: 1. 设计模式书籍 在豆瓣上搜索了一把,发现设计模式贯穿了人类生活的方方面面.还是回到Java与程序设计来吧. 打算先归类,再浏览,从 ...
随机推荐
- Springboot打包支持第三方jar
有时候我们需要的jar在maven里不存在,需要手动引入.比如,钉钉sdk <dependency> <groupId>com.aliyun</groupId> & ...
- NModbus类库使用
通过串口进行通信 : 1.将 NMobus 类库导入工程中,添加引用.命名空间.工程属性必须配置 为 .NET 4.0. 2.创建 SerialPort 类的一个实例,配置参数,打开串口,如: pub ...
- XMR恶意挖矿脚本处理笔记
一.登录 攻击者如何登录系统未能查出,所有日志已被清除.为防万一,把系统中没用的用户都删掉并修改其他用户密码. 二.被攻击后的表象 1.服务器资源被大量占用,资源占用率飙升: 2.服务器所有JS文件被 ...
- JS代码把JSON字符串转换为对象,计算对象的长度并把它转换为数字类型,把转换的值相加减
Number(JSON.parse(rowObject.RenewalProperty).length)-1
- 【转发】Cookie存储的值大小限制和个数问题
Cookie以及LocalStorage.SessionStorage的区别 缓存机制对于用户访问网页来说是很方便的.如果将用户名,偏好设定或者其他一些数据存储到客户端,而不必每次访问网页都输入数据, ...
- 将csv的数据导入mysql
手头有一份8MB的CSV文件需要分析,对于程序员来说,还有比在数据库里分析更愉快的事情吗? 所以让我们把CSV导入MYSQL吧. 一.首先按照文件列数创建相应的SQL表 例如: DROP TABLE ...
- maven项目中利用jmeter-maven-plugin插件直接执行jmeter jmx脚本
jmeter脚本需要执行脚本,先得下载jmeter并解压jmeter.如想在maven项目中通过mvn install 直接执行jmx文件,这样就能在测试服务器上通过一个命令就能执行下性能测试了,给自 ...
- js 检测变量是否存在
实际开发过程中,会有判断一个变量是否存在的场景 首先想到的是 if(a==undefined){ console.log("a is undefined") }else{ cons ...
- Thinkphp 关联模型和试图模型区别
关联模型主要在多表操作时使用,比如 user表,user_role表,role表 user_role字段:uid,rid,它作为中间表,负责将user和role之间的,1对1,1对多,多对多的关系进行 ...
- java中的数据加密2 对称加密
对称加密 也叫私钥加密. 采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密. 需要对加密和解密使用相同密钥的加密算法.由于其速度快,对 ...