Java 设计模式之单例模式(一)
原文地址:Java 设计模式之单例模式(一)
博客地址:http://www.extlight.com

一、背景
没有太多原由,纯粹是记录和总结自己从业以来经历和学习的点点滴滴。
本篇内容为 Java 设计模式系列的第一篇。
二、简单介绍
2.1 定义
单例模式是一种对象创建型模式,保证一个类只有一个实例,并且提供能对该实例加以访问的全局方法。
2.2 应用场景
操作系统的任务管理器
读取配置文件的类
数据库连接池
Javaweb 中的 Servlet 实例
Spring 创建的实例,默认为单例
...
三、实现方式
常用的实现方式有饿汉式、懒汉式和枚举类。
本篇文章主要讲饿汉式和懒汉式的单例模式。
共同点:将构造方法私有化,并且提供一个公共的方法访问该类的实例对象。
我们以任务管理器为例进行演示。
3.1 饿汉式
public class TaskManager {
private static TaskManager tm = new TaskManager();
private TaskManager() {
}
public static TaskManager getInstance() {
return tm;
}
}
优点:线程安全,不用加同步锁,因此在高并发时调用效率高。
缺点:不能懒加载,如果不使用该类的实例,浪费内存资源。
3.2 懒汉式
public class TaskManager {
private static TaskManager tm;
private TaskManager() {
}
public static synchronized TaskManager getInstance() {
if (tm == null) {
tm = new TaskManager();
}
return tm;
}
}
优点:实现懒加载,合理利用系统资源。
缺点:需要添加同步锁,高并发时调用效率不高。
注意点:上边的懒汉式可以通过反射机制创建多个实例。
public class Client {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.light.gof.singleton.TaskManager");
Constructor<?> constructor = clazz.getDeclaredConstructor(null);
// 跳过检测机制
constructor.setAccessible(true);
TaskManager tm1 = (TaskManager) constructor.newInstance();
TaskManager tm2 = (TaskManager) constructor.newInstance();
System.out.println(tm1 == tm2);// 结果返回 false
}
}
3.3 优化方式
将饿汉式和懒汉式的优点集中起来。
public class TaskManager {
private TaskManager() {
}
private static class InnerTaskManager {
private static final TaskManager tm = new TaskManager();
}
public static TaskManager getInstance() {
return InnerTaskManager.tm;
}
}
外部类没有静态属性,因此不会像饿汉式立即加载对象。
只有当调用公共方法(getInstance)时,才会加载静态内部类。加载内部类的过程是线程安全的。
内部类中通过 static final 确保内存中只有一个外部类的实例,因为实例变量(tm)只能被赋值一次。
四、UML 类图
类图表现如下:

五、性能比较
public class Client {
public static void main(String[] args) throws Exception {
// 线程数
int num = 10;
// 计数器
CountDownLatch cd = new CountDownLatch(num);
long t1 = System.currentTimeMillis();
for (int i = 0; i < num; i++) {
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
// 此处替换不同实现方式的单例代码进行测试
TaskManager tm = TaskManager.getInstance();
}
cd.countDown();
}
}).start();
}
// 主线程等待
cd.await();
System.out.println("耗时:" + (System.currentTimeMillis() - t1) + "ms");
}
}
测试结果:
| 实现方式 | 耗时 |
|---|---|
| 饿汉式 | 3ms |
| 懒汉式 | 12ms |
| 内部类方式 | 4ms |
测试结果是相对的,硬件配置不同,测试结果不同,但是对于这个 3 种实现方式,它们的用时比例应该大致相同。
Java 设计模式之单例模式(一)的更多相关文章
- java 设计模式之单例模式
-------Success is getting what you want, happiness is wanting what you get. java设计模式之单例模式(Singleton) ...
- 折腾Java设计模式之单例模式
博文原址:折腾Java设计模式之单例模式 单例模式 Ensure a class has only one instance, and provide a global point of access ...
- Java设计模式之单例模式(七种写法)
Java设计模式之单例模式(七种写法) 第一种,懒汉式,lazy初始化,线程不安全,多线程中无法工作: public class Singleton { private static Singleto ...
- java设计模式1——单例模式
java设计模式1--单例模式 1.单例模式介绍 1.1.核心作用:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点 1.2.常见场景 1.3.单例模式的优点 1.4.常见的五种单例模式实现 ...
- java设计模式之单例模式你真的会了吗?(懒汉式篇)
java设计模式之单例模式你真的会了吗?(懒汉式篇) 一.什么是单例模式? 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供 ...
- java设计模式之单例模式(几种写法及比较)
概念: Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建 ...
- java设计模式- (1)单例模式
参加校园招聘的笔试,发现公司都会考一些java设计模式,所以上网查询相关内容,总结常用的几种单例模式. 单例模式(Singleton Pattern)是 Java中最简单的设计模式之一.这种类型的设计 ...
- [转]JAVA设计模式之单例模式
原文地址:http://blog.csdn.net/jason0539/article/details/23297037 概念: java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主 ...
- java设计模式之单例模式(七种方法)
单例模式:个人认为这个是最简单的一种设计模式,而且也是在我们开发中最常用的一个设计模式. 单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个 ...
随机推荐
- 原生javascript-无间缝滚动,封装
目前支持的是竖向与横向滚动 http://lgy.1zwq.com/marScroll/ 现在分析下无间缝实现的基本思路(竖向例子): HTML结构: <div id="marScro ...
- Python抓取糗事百科成人版图片
最近开始学习爬虫,一开始看的是静觅的爬虫系列文章,今天看到糗事百科成人版,心里就邪恶了一下,把图片都爬下来吧,哈哈~ 虽然后来实现了,但还是存在一些问题,暂且不提,先切入正题吧,没什么好说的,直接上代 ...
- JS种正则表达式的基础用法
基础语法 元字符 常用元字符 含义 . 匹配除换行符以外的任意字符 \w 匹配字母数字或下划线 \W 匹配不是字母.数字.下划线的字符 \d 匹配数字,相当于[0-9] \D 匹配不是数字的字符 \s ...
- 【nyoj-1233】差值
描述 输入一个整数数组,将它们连接起来排成一个数,找出能排出的所有数字中最大,最小的两个,输出两个数的差值.例如输入数组{1, 2},则输出9. 输入 第一行输入一个整数T,表示有T组测试数 ...
- eureka -2 - 重要配置
Server 端配置 eureka.client.registerWithEureka :是否将自己注册到Eureka Server,默认是true,如果是单节点部署,切是server端,则设置成fa ...
- django中如何将多个app归到一个目录下。
1.当startapps 生成多个app后,为了便于管理,可新建一个apps目录,把应用全部剪切进apps. 如果是在pycharm中,会提示是否自动更新路径,这里要全部选择取消. QQ群交流:697 ...
- 如何使用JFinal开发javaweb
介绍开始: 编辑器:MyEclipse; 数据库:MySQL; 服务器:tomcat; 1 首先新建web项目 要强调的是Target runtime必须选择为None.然后点击两次Next,选中创建 ...
- EasyPusher安卓直播推流到EasyDarwin开源流媒体服务器工程简析
EasyPusher主要有三部分组件组成:采集,编码,叠加,上传.在这个基础上同时支持本地存储\后台预览的功能.主要业务模块与相关类之间的关系如图所示: Created with Raphaël 2. ...
- 基于 od 窗口的anti
虽然 odadvance 这类的插件 , 使用驱动将 od 的窗口 进行 隐藏,使用enumwindow ,无法枚举到od的窗口, 但是依然可以 使用r3 的方法 , 对od 窗口检测 之后可以使用 ...
- C语言共用体union
union共用体说明: 当一个共用体被声明时, 编译程序自动地产生一个变量, 其长度为联合中最大的变量长度的整数倍. 比如union中有{int x; double x1; char name[10] ...