设计模式学习--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与程序设计来吧. 打算先归类,再浏览,从 ...
随机推荐
- centos7安装postgres-10
目录 安装 下载yum repo 安装server和客户端 初始化db 启动Postgres 设置开机启动 修改data目录 停止服务 迁移data目录 重启 连接测试 修改允许远程其他IP连接 前一 ...
- 解决Nginx的13: Permission denied) while connecting to upstream
一.问题 做Nginx负载的时候,经常遇到这样的情况: // :: [crit] #: * connect() to failed (: Permission denied) while connec ...
- 研究傅里叶变换的一本好书<<快速傅里叶变换及其C程序>>
快速傅里叶变换及其C程序 <快速傅里叶变换及其C程序>是中国科学技术大学出版社出版的.本书系统地介绍了傅里叶变换的理论和技术,内容包括傅里叶变换(FT)的定义.存在条件及其性质,离散傅里叶 ...
- Sort_Buffer_Size 设置对服务器性能的影响
基础知识: 1. Sort_Buffer_Size 是一个connection级参数,在每个connection第一次需要使用这个buffer的时候,一次性分配设置的内存.2. Sort_Buffer ...
- 配置yum软件仓库(redhat 7.0)
第一步:切换到yum配置文件目录 执行:cd /etc/yum.repos.d/ 第二步:创建文件并进行编辑:vi rhel7.repo 写入如下内容:[rhel7] name=rhel7 ##名字随 ...
- 【Android】详解Android 网络操作
目录结构: contents structure [+] 判断网络 判断是否有网络连接 判断WIFI网络是否可用 判断MOBILE网络是否可用 获取当前网络连接的类型信息 监听网络 获取网络信息需要在 ...
- android保持服务不休眠(持续运行)以及唤醒屏幕的方法
假设有这样一个应用场景,一个服务一直在默默的工作(比如即时地获取服务器的消息),即使在屏幕已经因为长时间无操作而关闭,或者用户按了电源键让屏幕关闭,手机进入休眠状态,他必须依然在工作中.一旦从服务器获 ...
- windows环境telnet发送命令
telnet *.*.*.* port ,然后crtl+]进入命令模式,使用send发送消息,如:send hello,murphy 常用命令: open : 使用 openhostname 可以建立 ...
- Java对象的内存实际占用
一.打包和使用方法参考我之前的这篇文章,本文主要是更新了测量的类及方法,实际测试这个方法更准确. https://www.cnblogs.com/yoyotl/p/8421287.html 二.新的测 ...
- SNF快速开发平台--规则引擎介绍和使用文档
设计目标: a) 规则引擎语法能够满足分单,计费,WMS策略的配置要求.语法是一致和统一的 b) 能够在不修改规则引擎模块的情况下,加入任意一个新的规则:实现上述需求之外的规则配置需求 c) 运算速度 ...