• 单例模式-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 }
  • 相关阅读:
    (二)juc线程高级特性——CountDownLatch / Callable / Lock
    (一)juc线程高级特性——volatile / CAS算法 / ConcurrentHashMap
    配置tomcat的session共享
    elastic不错的官方文档(中文)
    elasticsearch java客户端api使用(一)
    Tomcat 没有自动解压webapp下的war项目文件问题
    Spring+Quartz实现定时任务
    注意的问题
    JMS之——ActiveMQ 高可用与负载均衡集群安装、配置(ZooKeeper + LevelDB + Static discovery)
    activemq持久化配置,设置为主从模式(带复制的主从模式,应用mysql数据库)
  • 原文地址:https://www.cnblogs.com/joshua-aw/p/6025833.html
Copyright © 2020-2023  润新知