java中五种单例模式

坚持每天写博文,记录开发中的点点滴滴

  • 饿汉式
    饿汉式
    饿汉式可以说是我们最先接触单例模式的例子了,是最基本的单例写法,也是最快最懒的方式。
    优点:简单好写;缺点:类加载就初始化了对象,影响应用启动速度
package singleton;
/**
 * 
* @ClassName: BaseSingleton 
* @Description: TODO(饿汉式单例模式) 
* @author Allen 
* @date 2018年1月11日 上午10:08:13 
*
 */
public class BaseSingleton {

    //第一步:私有构造
    private BaseSingleton() {

    }
    //第二步,私有静态对象
    private static BaseSingleton INSTANCE = new BaseSingleton();
    //第三步:提供对外获取方法
    public static BaseSingleton getBaseSingleton() {
        return INSTANCE;
    }
}
  • 懒汉式 主要是针对于饿汉式的缺点
    优点:只有第一次使用时才会初始化对象;缺点:多线程中可能出现创建多个对象
    其实就是加了个空判断
package singleton;
/**
 * 
* @ClassName: LazyLoadSingleton 
* @Description: TODO(懒汉式单例) 
* @author Allen 
* @date 2018年1月11日 上午10:17:27 
*
 */
public class LazyLoadSingleton {

    //第一步:私有构造
    private LazyLoadSingleton() {

    }
    //第二步:私有静态对象
    private static LazyLoadSingleton INSTANCE;
    //第三步:如果存在实例给出获取方法,不存在创建
    public LazyLoadSingleton getLazyLoadSingleton() {
        if(INSTANCE == null) {
            INSTANCE = new LazyLoadSingleton();
        }
            return INSTANCE;
    }
}
  • 同步锁式
    因为懒汉式的出现,虽然解决了饿汉式的不足,但也出现了多线程的问题。于是解决懒汉式的方式就出现了,那就是我们熟知的加锁Synchronized。
    优点:保证线程安全;缺点:每次都要加锁,但是获取不经济。
package singleton;
/**
 * 
* @ClassName: LazySynchronizedSingleton 
* @Description: TODO(同步锁式单例) 
* @author Allen 
* @date 2018年1月11日 上午10:24:02 
*
 */
public class LazySynchronizedSingleton {

    //第一步:私有构造
    private LazySynchronizedSingleton() {

    }
    //第二步:创建私有对象
    private static LazySynchronizedSingleton INSTANCE;
    //第三步:提供一个同步的对外获取方法
    public static synchronized LazySynchronizedSingleton getInstance() {
        if(INSTANCE == null) {
            INSTANCE = new LazySynchronizedSingleton();
        }
        return INSTANCE;
    }
}
  • 双重检测式
    第3种方式应该已经满足日常大部分的需求,但对我们程序员来说,不断的优化才是学习之道。那么针对每次获取都会加锁的问题,要怎么解决呢?双重检测式就出现了。
    优点:第一次获取时才会加锁;缺点:相比之下写法麻烦
package singleton;
/**
 * 
* @ClassName: DoubleCheckSingleton 
* @Description: TODO(双重检测单例模式) 
* @author Allen 
* @date 2018年1月11日 上午10:29:39 
*
 */
public class DoubleCheckSingleton {

    //第一步:私有构造
    private DoubleCheckSingleton() {

    }
    //第二步:创建静态对象
    private static volatile DoubleCheckSingleton INSTANCE;
    //提供对外方法
    public static DoubleCheckSingleton getInstance() {
        if(INSTANCE == null) {
            synchronized (DoubleCheckSingleton.class) {
                if(INSTANCE == null) {
                    INSTANCE = new DoubleCheckSingleton();
                }
            }
        }
        return INSTANCE;
    }
}

我们第二步用到了volatile,关于volatile不是本文的重点,所以这里不展开说明。在第三步中,我们首先判断一次空,如果是空,就加锁,然后再判断一次空,如果为空就创建。这样的好处就是上面优点说到的,只会锁一次。缺点大家也发现了,不仅要必须写volatile,方法中的步骤也不能错。
Java中Volatile关键字详解 https://www.cnblogs.com/zhengbin/p/5654805.html

  • 内部类式
    优点:懒加载、线程安全、代码少;缺点:暂无
    内部类Holder,里面有外部的实例。这怎么就满足懒汉式和线程安全呢?当我们应用初始化时,getInstance没有被调用,就没有实例对象,那就满足了懒汉式。当我们调用getInstance的时候,Java虚拟机为了保证类加载的安全性,所以这里就保证了线程安全。

整理自:详细的双语言(Java与Kotlin)5种单例模式 2018-01-08 FYNN_JASON 码个蛋

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章