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设计模式之单例模式(七种方法)
单例模式:个人认为这个是最简单的一种设计模式,而且也是在我们开发中最常用的一个设计模式. 单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个 ...
随机推荐
- 【问题解决记录】无法识别的标志“-sdlMode”,在“p2”中
本文为大便一箩筐的原创内容,转载请注明出处,谢谢:http://www.cnblogs.com/dbylk/ 这是本人第一次使用MarkDown编辑器,试试看效果-w-,下面是正文: 一.报错原因 昨 ...
- angularJS----filter
angularJS过滤器 过滤器(filter)正如其名,作用就是接收一个输入(隐式的接收数据源),通过某个规则进行处理,然后返回处理后的结果.主要用在数据的格式化上,例如获取一个数组中的子集,对数组 ...
- 安装使用babel-polyfill。让IE支持es6
安装 npm install --save-dev babel-polyfill 使用 在你的代码头部加载babel-polyfill,注意一定要在你的代码开始前,第一个js文件的顶部.如果是vue在 ...
- C#学习历程(七)[基础知识]
---恢复内容开始--- >>接受用户输入的整数 Console.readline():接受键盘输入的字符串,如果需要接受整数并输出,则需要字符串的转换. 一般建议使用Covert类中的方 ...
- LeetCode OJ:Climbing Stairs(攀爬台阶)
You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb ...
- APUE学习笔记——3.文件共享与fcntl介绍
基本概念 内核使用3个数据结构描述一个打开的文件:进程表.文件表.V节点表 首先了解3种数据结构的概念 1 进程表 每一个进程有一个进程表.进程表里是一组打开的文件描述符,如标 ...
- Recorder︱深度学习小数据集表现、优化(Active Learning)、标注集网络获取
一.深度学习在小数据集的表现 深度学习在小数据集情况下获得好效果,可以从两个角度去解决: 1.降低偏差,图像平移等操作 2.降低方差,dropout.随机梯度下降 先来看看深度学习在小数据集上表现的具 ...
- EasyDSS RTMP流媒体服务器videojs flash播放RTMP/HLS提示错误的解决方案
本文转自EasyDSS团队成员StarIT的博客:http://blog.csdn.net/staritstarit/article/details/73692715 问题 在博客<EasyDS ...
- Vim技能修炼教程(5) - 操作符实务
操作符实务 操作符复习 上次我们讲了操作符与文本对象的组合这样一个vim的强大功能.但是上节的知识点过于密集,可读性可能差了一点.不过没关系,重要的知识点在后面用到的时候我们可以先复习一下. 我们还是 ...
- CS231n课程笔记翻译3:线性分类笔记
译者注:本文智能单元首发,译自斯坦福CS231n课程笔记Linear Classification Note,课程教师Andrej Karpathy授权翻译.本篇教程由杜客翻译完成,巩子嘉和堃堃进行校 ...