单例模式

单例设计模式:属于创建型模式,提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。主要解决一个全局使用的类进行频繁的创建于销毁,耗费大量内存的问题。

注意事项:单例类只能有一个实例,单例类必须自己创建自己的实例并可以提供给其他对象使用

饿汉式

这种方式的优点是其为线程安全的,没有加锁,执行效率稍高一些

缺点则是类加载时就初始化,浪费内存(比如有很多类使用的是单例模式,程序在启动时就会创建这些对象,而不管你是否用到了这些类,从而导致程序启动较慢)

public class Singleton1 {

//    将构造函数私有化,让外部无法轻易的创建其对象(new的方式)
    private Singleton1(){}

//    static修饰的变量属于类,随着类的加载而加载,只加载一次
    private static Singleton1 instance = new Singleton1();

//    提供一个公开的访问接口,可以提供给其他对象使用
//    由于构造函数是私有化的,所以只能使用static关键字,可以被类直接调用
    public static Singleton1 getInstance(){
        return instance;
    }

}

懒汉式

懒汉式则是为了解决饿汉式,较为浪费内存的情况,只有在需要的时候才会创建对象,但懒汉式也有其缺点,可能会出现线程安全问题

线程不安全

public class Singleton2 {

//    单例模式私有构造函数是必须的
    private Singleton2(){}

//    同样提供一个类变量
    private static Singleton2 instance;

//    提供一个公开的访问方法,但其是会出现线程安全问题的
    public static Singleton2 getInstance(){
//        假如有两条线程t1和t2,此时t1抢到了执行权,进行判断并且判断实例为null,准备创建对象赋值时,被t2抢断
//        t2拿到执行权后顺利的创建完对象,此时t1又抢到了执行权,也去做创建对象并赋值的操作,便出现了创建出不同实例的情况
        if (instance == null){
            instance = new Singleton2();
        }
        return instance;
    }

}

线程安全

为了解决上面的问题,想到了使用synchronized关键字,将其改造为同步方法

public class Singleton3 {

    private Singleton3(){}

    private static Singleton3 instance;

//    我们在方法上添加synchronized关键字,使其变为静态同步方法
//    synchronized需要一个锁对象,在静态方法上的锁对象是类对象(在非静态方法上的锁对象是this,谁调用这个方法this就指向谁),一个类的类对象也只有一个,符合做锁对象的要求
//    为什么可以确定是类对象,还是因为static关键字,static修饰的方法和变量初始化在创建对象之前,此时还没有this
    public static synchronized Singleton3 getInstance(){
        if (instance == null){
            instance = new Singleton3();
        }
        return instance;
    }

}

双重校验锁

上面加了同步方法的懒汉式虽然是线程安全的,但是其执行效率会变慢,因为每次调用该方法都会等待上一个线程的锁,为了解决这个问题,我们可以使用同步代码块

public class Singleton4 {

    private Singleton4(){}

    private volatile static Singleton4 instance;

    public static Singleton4 getInstance(){

//        在第一个懒汉式中得知,在此处可能会出现线程安全问题,所以我们把同步代码块加在这里
//        锁对象也就是当前的类对象,这样虽然是线程安全的,并且比上一个线程安全的懒汉式看起来执行效率会更高
//        但是每一条线程进来都会等待锁进行判断实例的存在,可以再做优化
        synchronized (Singleton4.class){
            if (instance == null){
                instance = new Singleton4();
            }
        }
        return instance;
    }

}
public class Singleton4 {

    private Singleton4(){}

    private static Singleton4 instance;

    public static Singleton4 getInstance(){

//        可以再同步代码块外面再加一层校验,这样其他线程不必等待锁进行判断,也保证了创建对象的安全性
        if (instance == null){
            synchronized (Singleton4.class){
                if (instance == null){
                    instance = new Singleton4();
                }
            }
        }
        return instance;
    }

}
Copyright © TaoQZ 2019 all right reserved,powered by Gitbook作者联系方式:taoqingzhou@gmail.com 修订时间: 2024-11-19 17:25:43

results matching ""

    No results matching ""

    results matching ""

      No results matching ""