zoukankan      html  css  js  c++  java
  • 单例模式-Singleton

    单例(Singleton)是一种常用的设计模式。在Java应用中,单例模式能保证在一个JVM中,该对象只有一个实例对象存在。这样的模式有几个好处:

    1. 有些大型类的对象创建比较复杂,系统开销大,可以考虑使用单例模式。

    2. 省去了new操作符,降低了系统内存的使用频率,减轻GC压力。

    3. 有些类控制着整个业务流程,如果可以创建多个对象的话,系统就乱了。只有使用单例模式,才能保证核心引擎独立控制整个流程。

     

    先写一个饿汉式的单例模式:这种模式的好处就是不会产生线程安全问题

    1 private class Singleton {           
    2     private static Singleton instance = new Singleton(); 
    3     
    4     private Singleton() {}
    5 
    6     public static Singleton getInstance() {
    7         return instance;           
    8     }
    9 }

    通过这个简单的代码,可以看出单例模式有以下特性:

    1. 构造函数私有化:防止对象在外部被创建

    2. 公有的获取实例的函数getInstance():可以从外部通过Singleton.getInstance()获取实例

    3. 私有且静态的Singleton类型成员变量

    本人认为饿汉式单例模式已经够用了,因为使用单例模式就为了使用它的实例对象,在类加载时创建和在使用时创建没有很大区别

    下面介绍一下懒汉式单例模式:可能会有线程安全性问题

     1 public class Singleton {  
     2   
     3     private static Singleton instance = null;  
     4   
     5     private Singleton() {}  
     6 
     7     public static Singleton getInstance() {  
     8         if (instance == null) {  
     9             instance = new Singleton();  
    10         }
    11         return instance;  
    12     }
    13 }

    为解决线程安全问题,可以对方法加上synchronized,得到下面的单例模式:

     1 public class Singleton {  
     2   
     3     private static Singleton instance = null;  
     4   
     5     private Singleton() {}  
     6 
     7     public static synchronized Singleton getInstance() {  
     8         if (instance == null) {  
     9             instance = new Singleton();  
    10         }
    11         return instance;  
    12     }
    13 }

    此方式类似于:

     1 public class Singleton {  
     2   
     3     private static Singleton instance = null;  
     4   
     5     private Singleton() {}  
     6 
     7     public static Singleton getInstance() {  
     8         synchronized(instance) {
     9             if (instance == null) {  
    10                 instance = new Singleton();  
    11             }
    12         }
    13         return instance;  
    14     }
    15 }

    但是,此方法由于每次调用getInstance()时都会访问一次锁(为对象加锁),但是实际的情况是只有第一次调用时才应该加锁,因此效率低下,可以使用两次判断(double check)方式提高锁效率:

     1 public class Singleton {  
     2   
     3     private static Singleton instance = null;  
     4   
     5     private Singleton() {}  
     6 
     7     public static Singleton getInstance() {  
     8         if(instance == null) {
     9             synchronized(instance) {
    10                 if (instance == null) {  
    11                     instance = new Singleton();  
    12                 }
    13             }
    14         }
    15         return instance;  
    16     }
    17 }

    此方法类似于:

     1 public class Singleton {  
     2   
     3     private static Singleton instance = null;  
     4   
     5     private Singleton() {}  
     6 
     7     public static Singleton getInstance() {  
     8         if (instance == null) {
     9             buildInstance();
    10         }
    11         return instance;  
    12     }
    13 
    14     private static synchronized void buildInstance() {
    15         if (instance == null) {  
    16             instance = new Singleton();  
    17         }
    18     }
    19 }

    由于JVM内部的类加载机制能够保证当一个类被加载的时候,加载过程是线程互斥的。这样,我们可以使用内部类来维护单例的实现:当我们第一次调用getInstance()的时候,JVM能够帮我们保证instance只被创建一次,这样我们就不用担心线程安全问题。同时该方法只会在第一次调用的时候使用互斥机制,这样又解决了效率低的问题。这样我们可以得到下面的单例模式:

     1 public class Singleton {  
     2   
     3     private Singleton() { } 
     4  
     5     private static class SingletonFactory {  
     6         private static Singleton instance = new Singleton();  
     7     } 
     8   
     9     public static Singleton getInstance() {  
    10         return SingletonFactory.instance;  
    11     } 
    12 }

    追加:只有一个元素的枚举即是单例

    1 public enum Singleton {
    2     SINGLETON
    3 }
  • 相关阅读:
    suseoj 1211: 子集和问题 (dfs)
    suseoj 1210: 会场安排问题 (贪心)
    suseoj 1209: 独立任务最优调度问题(动态规划)
    四级词汇(二)
    四级单词(一)
    nyoj 84-阶乘的0 (规律题)
    nyoj 83-迷宫寻宝(二) (计算几何, 叉积)
    nyoj 82-迷宫寻宝(一) (多重BFS)
    nyoj 79-拦截导弹 (动态规划)
    nyoj 78-圈水池 (凸包)
  • 原文地址:https://www.cnblogs.com/joshua-aw/p/6025833.html
Copyright © 2011-2022 走看看