一、单例模式(Singleton)

1、单例模式应用场景:

  ①Servlet
  ②任务管理器
  ③链接池
  ④Spring中每个 bean 默认是单例
  ⑤网站计数器

2、单例要求

  ①构造器私有
  ②私有的静态变量
  ③公共的静态的可以访问私有的静态变量的方法

结论:由结果可以得知单例模式为一个面向对象的应用程序提供了对象惟一的访问点,不管它实现何种功能,整个应用程序都会同享一个实例对象。
二、单例模式的实现方式

1、饿汉式
  线程安全、立即加载、资源利用率低、调用效率高

package cn.com.zfc.gof01.singleton;

/**
*
* @title Singleton01
* @describe 饿汉式实现单例模式
* @author 张富昌
* @date 2017年3月27日上午8:40:02
*/
public class Singleton01 {

  // 天然的线程安全的,类加载是立即加载这个实例
  private static Singleton01 instance = new Singleton01();

  / 构造器私有化
  private Singleton01() {

  }

  // 方法没有同步,效率比较高
  public static Singleton01 getInstance() {
    return instance;
  }
}

2、懒汉式
  线程安全、延迟加载、资源利用率高、调用效率低

package cn.com.zfc.gof01.singleton;

/**
*
* @title Singleton02
* @describe 懒汉式实现单例模式
* @author 张富昌
* @date 2017年3月27日上午8:45:42
*/
public class Singleton02 {

  private static Singleton02 instance = null;

  //构造其私有化
  private Singleton02() {
  }

  //公共,同步,静态
  public static synchronized Singleton02 getInstance() {
    if (instance == null) {
      instance = new Singleton02();
    }
    return instance;
  }
}

3、双重检索式
  线程安全、延迟加载、资源利用率高、调用效率高、但不稳定

package cn.com.zfc.gof01.singleton;

/**
*
* @title Singleton03
* @describe 双重检测锁式实现单例模式(不建议使用)
* @author 张富昌
* @date 2017年3月27日上午8:52:59
*/
public class Singleton03 {

  private static Singleton03 instance = null;

  private Singleton03() {

  }

  public static Singleton03 getInstance() {
    if (instance == null) {
      Singleton03 sc;
      synchronized (Singleton03.class) {
        sc = instance;
        if (sc == null) {
          synchronized (Singleton03.class) {
            if (sc == null) {
              sc = new Singleton03();
            }
          }
          instance = sc;
        }
      }
    }
    return instance;
  }

}

4、静态内部类式(相比于懒汉式更好)
  线程安全、延迟加载、资源利用率高、调用效率高

package cn.com.zfc.gof01.singleton;

/**
*
* @title Singleton04
* @describe 静态内部类式实现单例模式
* @author 张富昌
* @date 2017年3月27日上午8:54:40
*/
public class Singleton04 {

  // 构造器私有化
  private Singleton04() {

  }

  // 静态内部类
  private static class StaticInnerClass {
    private static final Singleton04 INSTANCE = new Singleton04();
  }

  public static Singleton04 getInstance() {
    return StaticInnerClass.INSTANCE;
  }

}

5、枚举单例式(相比于饿汉式更好)
  线程安全、立即加载、可以天然的防止反射和反序列化

package cn.com.zfc.gof01.singleton;

/**
*
* @title Singleton05
* @describe 枚举式实现单例模式
* @author 张富昌
* @date 2017年3月27日上午9:01:59
*/
public enum Singleton05 {
  // 单例对象
  INSTANCE;

  // 如果要对该单例对象进行额外的操作,则加入方法
  public void singlrtonOperation() {

  }

}

三、测试多线程环境下五种创建单例模式的效率

package cn.com.zfc.gof01.singleton.test;

import java.util.concurrent.CountDownLatch;

import cn.com.zfc.gof01.singleton.Singleton05;

/**
*
* @title SingletonTest
* @describe 测试多线程环境下五种创建单例模式的效率
* @author 张富昌
* @date 2017年3月27日上午9:24:58
*/
public class SingletonTest {
  public static void main(String[] args) throws Exception {

    long start = System.currentTimeMillis();
    int threadNum = 10;
    // A synchronization aid that allows one or more threads to wait until a
    // set of operations being performed in other threads completes.
    // 计数器(一个线程执行完成就减1)
    final CountDownLatch countDownLatch = new CountDownLatch(threadNum);

    for (int i = 0; i < threadNum; i++) {
      // 多线程测试
      new Thread(new Runnable() {
        @Override
        public void run() {

          for (int i = 0; i < 1000000; i++) {
            // 饿汉式,
            // Object o = Singleton01.getInstance();
            // 懒汉式,最慢
            // Object o = Singleton02.getInstance();
            // 双重检测锁式,不稳定,不建议使用
            // Object o = Singleton03.getInstance();
            // 静态内部类
            // Object o = Singleton04.getInstance();
            // 枚举式
            Object o = Singleton05.INSTANCE;
          }

          // 一个线程执行完成就减1
          countDownLatch.countDown();
        }
      }).start();
    }

    // 阻塞
    countDownLatch.await(); // main线程阻塞,直到计数器变为0,才会继续往下执行!

    long end = System.currentTimeMillis();
    System.out.println("总耗时:" + (end - start));
  }
}

四、什么是线程安全?

  如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

  或者说:一个类或者程序所提供的接口对于线程来说是原子操作,或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题,那就是线程安全的。

Java设计模式GOF之单例模式的更多相关文章

  1. Java设计模式之《单例模式》及应用场景

    摘要: 原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6510196.html 所谓单例,指的就是单实例,有且仅有一个类实例,这个单例不应该 ...

  2. Java设计模式之【单例模式】

    Java设计模式之[单例模式] 何为单例 在应用的生存周期中,一个类的实例有且仅有一个 当在一些业务中需要规定某个类的实例有且仅有一个时,就可以用单例模式 比如spring容器默认初始化的实例就是单例 ...

  3. Java设计模式GOF之6大设计原则

    Java设计模式GOF之6大设计原则原则 1.开闭原则(Open Close Principle) 一个软件实体如类.模块和函数应该对扩展开放,对修改关闭. 开闭原则是面向对象的可复用设计的第一块基石 ...

  4. Java设计模式中的单例模式

    有时候在实际项目的开发中,我们会碰到这样一种情况,该类只允许存在一个实例化的对象,不允许存在一个以上的实例化对象,我们将这种情况称为Java设计模式中的单例模式.设计单例模式主要采用了Java的pri ...

  5. 重学 Java 设计模式:实战单例模式

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 5个创建型模式的最后一个 在设计模式中按照不同的处理方式共包含三大类:创建型模式.结 ...

  6. java设计模式-----4、单例模式

    单例模式是一种对象创建型模式,使用单例模式,可以保证为一个类只生成唯一的一个实例对象.也就是说,在整个程序空间中,该类只存在一个实例对象. 其实,GoF对单例模式的定义是:保证一个类,只有一个实例存在 ...

  7. Java设计模式4:单例模式

    前言 非常重要,单例模式是各个Java项目中必不可少的一种设计模式.本文的关注点将重点放在单例模式的写法以及每种写法的线程安全性上.所谓"线程安全性"的意思就是保证在创建单例对象的 ...

  8. 10.Java设计模式 工厂模式,单例模式

    Java 之工厂方法和抽象工厂模式 1. 概念 工厂方法:一抽象产品类派生出多个具体产品类:一抽象工厂类派生出多个具体工厂类:每个具体工厂类只能创建一个具体产品类的实例. 即定义一个创建对象的接口(即 ...

  9. Java设计模式探讨之单例模式

    单例模式是在平时的项目开发中比较常见的一种设计模式,使用比较普遍,网上的资料也是一抓一大把,小Alan也来凑凑热闹,为以后充实点设计模式相关的内容做个简单的开篇. 单例模式是一种创建对象的模式,用于产 ...

随机推荐

  1. 快速排序的C语言实现

    #include <stdio.h> int qSort(int a[],int i,int j) { int h = i; int r = j; int x = a[h]; int f ...

  2. 自己用到的相关Linux命令,谨以记录

    1.查看磁盘使用情况 df -h(方便看些) df -l(字节大小,不方便看) 2.查看根目录下文件/文件夹大小 du -sh /*(/*表示根目录下所有文件) 3.查看文件列表时显示文件大小 ll ...

  3. vc中Error spawning cl.exe错误的解决方法.

    可能很多人在安装VC 6.0后有过点击“Compile”或者“Build”后被出现的 “Compiling... ,Error spawning cl.exe”错误提示给郁闷过.很多人的 选择是重装, ...

  4. Linux系统(二)软件的安装与卸载

    序言 上一篇我们了解啦Linux系统中,根目录下的各个文件夹是做什么用的啦,也学会文件如何压缩打包.那么接下来我们就该用到这个系统啦.用这个系统,就是用这个系统的软件,那么我们对我们需要的软件如何安装 ...

  5. Scala入门 【1】

    Scala入门 [1] 转载请注明出处:http://www.cnblogs.com/BYRans/ 1 基础 val定义的为常量,var为变量 val name:Type = ***,变量名后加冒号 ...

  6. CEOI 2014 wall (最短路)

    描述:给定一个网格图,每个区间可能会有城市,求在边上建墙使无法从外边到达所有城市切所有城市必须联通 n,m<=400 首先对于30%的数据,n,m<=10我们可以考虑用数位dp来解决这个问 ...

  7. hibernate中save()、update()、saveOrUpdate()的区别

    save()方法很显然是执行保存操作的,如果是对一个新的刚new出来的对象进行保存,自然要使用这个方法了,数据库中没有这个对象. update()如果是对一个已经存在的托管对象进行更新那么肯定是要使用 ...

  8. 磁盘工作原理与IO性能分析

    最近,在研究如何优化产品设备的磁盘IO性能,需要深入研究磁盘及文件系统原理和工作机制,下面简要总结下关于磁盘方面的东西,下篇文章再分享文件系统的. 机械磁盘结构: 无论哪种机械硬盘,都主要由盘片.磁头 ...

  9. jQ试题的总结

    jQuery习题的一些总结   1.在div元素中,包含了一个<span>元素,通过has选择器获取<div>元素中的<span>元素的语法是? 提示使用has $ ...

  10. js 各进制前缀 及 转换

    二进制前缀0b var a=0b11;//a=3 八进制前缀0 var a=011;//a=9 十进制不用前缀 十六进制前缀0x var a=0x11;//a=17 数字转各进制字符串用num.toS ...