原文地址: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. 玲珑oj 1117 线段树+离线+离散化,laz大法

    1117 - RE:从零开始的异世界生活 Time Limit:1s Memory Limit:256MByte Submissions:438Solved:68 DESCRIPTION 486到了异 ...

  2. 四元数 Quaternion

    最近在重写自己游戏引擎的场景管理模块,重温了一下有关四元数的一些知识,在此做一下简单的笔记. 四元数可以用来准确地描述三维矢量的旋转,并且可以有效地表达多个旋转操作的叠加,因此在三维游戏引擎的场景管理 ...

  3. Caesars Cipher

    让上帝的归上帝,凯撒的归凯撒. 下面我们来介绍风靡全球的凯撒密码Caesar cipher,又叫移位密码. 移位密码也就是密码中的字母会按照指定的数量来做移位. 一个常见的案例就是ROT13密码,字母 ...

  4. rsync技巧

    rsync格式: # 拷贝本地文件.当SRC和DES路径信息都不包含有单个冒号”:”分隔符时就启动这种工作模式.如:rsync -a /data /backup rsync [OPTION]... S ...

  5. hdu 4081 Qin Shi Huang's National Road System 树的基本性质 or 次小生成树思想 难度:1

    During the Warring States Period of ancient China(476 BC to 221 BC), there were seven kingdoms in Ch ...

  6. 优化JDBC封装

    可重用性较强的JDBC封装 以下为代码,注释中写了主要思想 主类 com.util.JDBCUtil.java package com.util; import java.lang.reflect.F ...

  7. 通过网页或Serverice远程系统网站(服务)所在服务器本地的应用程序(未成功)

    近日接了一个奇葩需求,内容如题. 实现过程中遇到一些问题,特将实现过程记录于此,供备忘及参考. 首先尝试了正常启动进程的方法,代码如下: public string RunSPApp() { Proc ...

  8. ES查询index对应的mapping信息

    private void getMappingByIndex(String indices) throws IOException { GetMappingsRequest getMappingsRe ...

  9. .net的session详解

    http://blog.csdn.net/justin_wkf/article/details/5746914#comments

  10. root用户下使用sqlplus登录Oracle数据库

    1.把环境变量添加到root用户的环境变量里面2.执行 chmod -R 6777 /tmp           chmod -R 6777 /usr/tmp           chmod -R 6 ...