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设计模式之单例模式(七种方法)
单例模式:个人认为这个是最简单的一种设计模式,而且也是在我们开发中最常用的一个设计模式. 单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个 ...
随机推荐
- Project facet Java 1.8 is not supported by target runtime Apache Tomcat v7.0.
找到项目下的“.settings”
- Python中的map和reduce函数简介
①从参数方面来讲: map()函数: map()包含两个参数,第一个是参数是一个函数,第二个是序列(列表或元组).其中,函数(即map的第一个参数位置的函数)可以接收一个或多个参数. reduce() ...
- 双系统下ubuntu不能访问658GB卷,磁盘挂载失败。
win10+ubuntu双系统出现以下错误: Error mounting /dev/sda5 at /media/captain/AC8CF85B8CF8218E: Command-line `mo ...
- linux中的redis缓存服务器
Linux中的Redis缓存服务器 一.Redis基础部分: 1.redis介绍与安装比mysql快10倍以上 *****************redis适用场合**************** 1 ...
- poj 3348 Cows 凸包 求多边形面积 计算几何 难度:0 Source:CCC207
Cows Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 7038 Accepted: 3242 Description ...
- 【CodeForces - 870C】
题意: 计算一个整数最多可以拆分为多少个合数(要求拆分的全是合数).例如:12的拆分法案是12=4+4+4. 合数是指除了1之外的非素数(正整数). 思路: 偶数的话用4.6就可以满足,奇数的话减去一 ...
- TPCC-MySQL(转自imysql.com)
[Tpcc-mysql] Tpcc-mysql是percona基于tpcc衍生出来的产品,专用于mysql基准测试,其源码放在bazaar(Bazaar是一个分布式的版本控制系统,采用 GPL 许可协 ...
- 【Sizzle学习】之关于【初探 jQuery 的 Sizzle 选择器】这篇文章里的小bug
[题记]不可否认,这篇文章写得非常好,但是今天我在看sizzle源码的时候,发现这文章有一地方说的不妥.重现:当selectors为"p.class1>p.class2",j ...
- WordCount-个人项目2
我的这个WC程序实现了对txt文件中的数据的计数,算出程序中有多少单词.字符数.行数还有空格数.以及长度. 项目源代码参考:http://www.cnblogs.com/sunbuqiao/p/531 ...
- Redis数据结构:字典(hash表)
使用场景: # set person name "tom" # set person name "jerry" 1. 字典结构: 哈希表数据结构 typedef ...