JAVA单例的几种实现

一、饿汉式

public class Singleton{
         //定义一个变量来存储创建好的类实例,直接在这里创建,只能创建一次
         private static Singleton uniqueInstance = new Singleton();
         //私有化构造方法,可以在内部控制创建实例的数目
         private Singleton(){
                   //
         }
         //定义一个方法来为客户端提供类实例
         public static Singleton getInstance(){
                   return uniqueInstance;
         }
}

        最简单的单例实现,典型的空间换时间,当类装载的时候就会创建类实例,不管你用不用,先创建出来,然后每次调用的时候,就不需要在判断了,节省了运行时间。

二、懒汉式

public class Singleton{
         //定义一个变量来存储创建好的实例
         private static Singleton uniqueInstance = null;
         //私有化构造方法,可以在内部控制创建实例的数目
         private Singleton(){
                   //
         }
         //定义一个方法来为客户端提供类实例
         public static synchronized Singleton getInstance(){
                   //判断存储实例的变量是否有值
                   if(uniqueInstance == null){
                            //如果没有,就创建一个类实例,并把值赋给存储类实例的变量
                            uniqueInstance = new Singleton();
                   }
                   //如果有就直接使用
                   return uniqueInstance();
         }
}

        时间-空间上刚好与饿汉相反,可以实现延迟加载,但是需要注意多线程调用的效率问题。

三、内部类实现

public class Singleton{
         /*类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例没有绑
          *定关系,而且在由在调用时才会装载,从而实现了延迟加载
          */
         private static class SingletonHolder{
                   //静态初始化器,由JVM来保证线程安全
                   private static Singleton instance = new Singleton();
         }
         private Singleton(){
         }
         private static Singleton getInstance(){
                   return SingletonHolder.instance;
         }
}

        由虚拟机来保证它的线程安全性。

四、缓存方式

import java.util.* ;
public class SingletonCache{
        private final static String DEFAULT_KEY = "One" ;
        private static Map<String,SingletonCache> map = new HashMap<String,SingletonCache>
        private SingletonCache(){
                //
        }
        public static SingletonCache getInstance(){
                SingletonCache instance = (SingletonCache)map.get(DEFAULT_KEY) ;
                if(instance==null){
                        instance = new SingletonCache() ;
                        map.put(DEFAULT_KEY,instance) ;
                }
        }
}

    该种实现方式可以扩展为实例数量固定的情形,如要求某个类最多创建3个实例的情形。

五、枚举方式

public enum Singleton{
         //定义一个枚举的元素,它代表了Singleton的一个实例
         uniqueInstance ;
         private Singleton() {
                   //准备初始化工作
         }
         public void singletonOperate(){
                   //功能处理
         }
}

    最简单、高效、安全的实现方式。

六、双重加锁

public class Singleton{
         private volatile static Singleton instance = null ;
         private Singleton(){
         }
         public static Singleton getInstance(){
                   //先检查实例是否存在,如果不存在才进入下面的同步块
                   if(instance == null){
                            //同步块,线程安全地创建实例
                            synchronized(Singleton.class){
                                     //再次检查实例是否存在,如果不存在才真正地创建实例
                                     if(instance == null){
                                               instance = new Singleton() ;
                                     }
                            }
                   }
                   return instance ;
         }
}

       使用“双重检查加锁”的方式来实现,就可以既实现线程安全,又能够使性能不受到大的影响。所谓双重检查加锁机制,指的是:并不是每次进入getInstance方法都需要同步,而是先不同步,进入方法过后,先检查实例是否存在,如果不存在才进入下面的同步块,这是第一重检查。进入同步块过后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查。这样一来,就只需要同步一次了,从而减少了多次在同步情况下进行判断所浪费的时间。

    双重检查加锁机制的实现会使用一个关键字volatile,它的意思是:被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量。


转载于:https://my.oschina.net/vbird/blog/192726

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值