原文地址:Java 设计模式之单例模式(一)

博客地址:http://www.extlight.com

一、背景

没有太多原由,纯粹是记录和总结自己从业以来经历和学习的点点滴滴。

本篇内容为 Java 设计模式系列的第一篇。

二、简单介绍

2.1 定义

单例模式是一种对象创建型模式,保证一个类只有一个实例,并且提供能对该实例加以访问的全局方法。

2.2 应用场景

  1. 操作系统的任务管理器

  2. 读取配置文件的类

  3. 数据库连接池

  4. Javaweb 中的 Servlet 实例

  5. 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 设计模式之单例模式(一)的更多相关文章

  1. java 设计模式之单例模式

    -------Success is getting what you want, happiness is wanting what you get. java设计模式之单例模式(Singleton) ...

  2. 折腾Java设计模式之单例模式

    博文原址:折腾Java设计模式之单例模式 单例模式 Ensure a class has only one instance, and provide a global point of access ...

  3. Java设计模式之单例模式(七种写法)

    Java设计模式之单例模式(七种写法) 第一种,懒汉式,lazy初始化,线程不安全,多线程中无法工作: public class Singleton { private static Singleto ...

  4. java设计模式1——单例模式

    java设计模式1--单例模式 1.单例模式介绍 1.1.核心作用:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点 1.2.常见场景 1.3.单例模式的优点 1.4.常见的五种单例模式实现 ...

  5. java设计模式之单例模式你真的会了吗?(懒汉式篇)

    java设计模式之单例模式你真的会了吗?(懒汉式篇) 一.什么是单例模式? 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供 ...

  6. java设计模式之单例模式(几种写法及比较)

    概念: Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建 ...

  7. java设计模式- (1)单例模式

    参加校园招聘的笔试,发现公司都会考一些java设计模式,所以上网查询相关内容,总结常用的几种单例模式. 单例模式(Singleton Pattern)是 Java中最简单的设计模式之一.这种类型的设计 ...

  8. [转]JAVA设计模式之单例模式

    原文地址:http://blog.csdn.net/jason0539/article/details/23297037 概念: java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主 ...

  9. java设计模式之单例模式(七种方法)

    单例模式:个人认为这个是最简单的一种设计模式,而且也是在我们开发中最常用的一个设计模式. 单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个 ...

随机推荐

  1. 已经安装了node和npm,输入node -v 未找到命令

    昨天虚拟机上安装了nvm.node.npm,今天打开输入node -v,就显示未找到命令 输入nvm --version 发现还是有nvm版本的,不然都要以为刚配好的虚拟机又要重新安装... 再输入 ...

  2. UVALive-5135 Mining Your Own Business (无向图的双连通分量)

    题目分析:在一张无向图中,将一些点涂上黑色,使得删掉图中任何一个点时,每个连通分量至少有一个黑点.问最少能涂几个黑点,并且在涂最少的情况下有几种方案. 题目分析:显然,一定不能涂割点.对于每一个连通分 ...

  3. Linux命令nohup+screen 转

    如果想在关闭ssh连接后刚才启动的程序继续运行怎么办,可以使用nohup.但是如果要求第二天来的时候,一开ssh,还能查看到昨天运行的程序的状态,然后继续工作,这时nohup是不行了,需要使用scre ...

  4. 034——VUE中表单控件处理之使用vue控制radio表单的实例操作

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. CMDB开发(需求分析)

    浅谈ITIL TIL即IT基础架构库(Information Technology Infrastructure Library, ITIL,信息技术基础架构库)由英国政府部门CCTA(Central ...

  6. 在IE中MVC控制器中返回JSON格式的数据时提示下载

    最近做项目时,视图中用jquery.form.js异步提交表单时,接收的是JSON格式的数据,但是奇怪的是在IE中提示下载文件,其他浏览器中一切正常,下载后,里面的内容就是在控制器中返回的数据.代码如 ...

  7. Deepgreen DB简介(转)

    原文链接   Deepgreen DB 全称 Vitesse Deepgreen DB,它是一个可扩展的大规模并行(通常称为MPP)数据仓库解决方案,起源于开源数据仓库项目Greenplum DB(通 ...

  8. R︱Yandex的梯度提升CatBoost 算法(官方述:超越XGBoost/lightGBM/h2o)

    俄罗斯搜索巨头 Yandex 昨日宣布开源 CatBoost ,这是一种支持类别特征,基于梯度提升决策树的机器学习方法. CatBoost 是由 Yandex 的研究人员和工程师开发的,是 Matri ...

  9. Graham扫描法

    Graham扫描法求凸包的模板 运行之后可以得到存有凸包顶点的栈s和栈顶指针top,n代表总点数 这个模板我当时调了很久,主要难点有两个,一个是正确的极角排序,一个是出栈入栈的细节操作,逆时针扫描,这 ...

  10. debian 8.1 安装idempiere 2.1 X64 笔记

    接上文.当虚拟服务器和虚拟机搭建完成后.登陆debian 8.1 X64. 进入虚拟服务器控制台.打开虚拟机.root登陆.(留好初始状态系统快照.以便系统恢复.) 由于之前debian8.1X64默 ...