一、单例模式(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. oracle中的net manager 无法配置

    今天遇到配置oracle net manager时无法配置,点击服务命名下面没有节点,绿色加号也没有反应 后在网上查到是因为tnsnames文件中的有空格存在导致 文件路径:oracle/produc ...

  2. 读书笔记 effective c++ Item 14 对资源管理类的拷贝行为要谨慎

    1. 自己实现一个资源管理类 Item 13中介绍了 “资源获取之时也是初始化之时(RAII)”的概念,这个概念被当作资源管理类的“脊柱“,也描述了auto_ptr和tr1::shared_ptr是如 ...

  3. Asp.net mvc 知多少(八)

    本系列主要翻译自<ASP.NET MVC Interview Questions and Answers >- By Shailendra Chauhan,想看英文原版的可访问[http: ...

  4. js设计模式--迭代器模式

    迭代器模式: 迭代器模式提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露该方法中的内部表示.js中我们经常会封装一个each函数用来实现迭代器. 理解的意思:提供一个方法,去把对象的每一项按 ...

  5. BZOJ 3653: 谈笑风生(DFS序+可持久化线段树)

    首先嘛,还是太弱了,想了好久QAQ 然后,这道题么,明显就是求sigma(size[x]) (x是y的儿子且层树小于k) 然后就可以发现:把前n个节点按深度建可持久化线段树,就能用前缀和维护了 其实不 ...

  6. angular、vue使用感受

    最近开始学习并使用vue.js,并使用vue+node开发了一个移动端APP来练手,下面想聊聊我对于vue的粗浅看法,并将它和angular进行一些对比: 1.vue是一个轻量.高效的前端组件化框架, ...

  7. 基于Blod的ajax进度条下载实现

    普通的浏览器下载 在web开发中,如果要实现下载功能,往往都是使用新开web页面或者是使用iframe的形式.实现起来其实很简单: <a target="_blank" hr ...

  8. SVN服务搭建

    yum方式搭建: 1,安装SVN服务端 直接用apt-get或yum安装subversion即可(当然也可以自己去官方下载安装) sudo apt-get install subversion 2,创 ...

  9. springmvc 获取request 和 java路径分隔符 在windows 和linux 下自动判断的方法

    //获取requert HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestA ...

  10. 移动H5开发入门知识,CSS的单位汇总与用法

    说到css的单位,大家应该首先想到的是px,也就是像素,我们在网页布局中一般都是用px,但是近年来自适应网页布局越来越多,em和百分比也经常用到了.然后随着手机的流行,web app和hybrid a ...