Java单例模式

1、饿汉模式:直接创建对象,不存在线程安全问题

1.1、直接实例化(简洁直观)
/**
 * @author luojianhui
 * @date 2018/11/2
 * 直接实例化
 * 1.构造器私有化
 * 2.自行创建,并用静态变量保存
 * 3.向外提供这个实例
 * 4.强调这是一个单例,用final修改
 * 5.随着类加载初始化,静态修饰对象也会创建
 */
public class Singleton1 {

    public static final Singleton1 INGLETON=new Singleton1();

    private Singleton1() {

    }
}
1.2、枚举式(最简洁)(jdk 1.5之后)
/**
 * @author luojianhui
 * @date 2018/11/2
 * 枚举式
 * 1.枚举类型:表示该类型的对象是有限的几个
 * 2.限定为一个,就成为单例了
 */
public enum Singleton2 {
    INSTANCE
}
1.3、静态代码块(适合复杂实例化)
/**
 * @author luojianhui
 * @date 2018/11/2
 * 静态代码块
 * 1.随着类加载初始化,静态代码块也执行
 */
public class Singleton3 {

    public static final Singleton3 SINGLETON;
    private String info;

    static {
        try {
            //初始化Properties
            Properties pro = new Properties();
            //文件最终编译是在类路径下
            pro.load(Singleton3.class.getClassLoader().getResourceAsStream("singleton.properties"));
            INGLETON = new Singleton3(pro.getProperty("info"));
        } catch (IOException e) {
            throw new RuntimeException();
        }
    }

    private Singleton3(String info) {
        this.info = info;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    @Override
    public String toString() {
        return "Singleton3{" +
                "info='" + info + '\'' +
                '}';
    }
}

singleton.properties 放在src目录下

info=ash

测试:

public class TestDemo{
    public static void main(String[] args) {
        Singleton3 ingleton = Singleton3.INGLETON;
        System.out.println(ingleton.toString());
        //输出结果:Singleton3{info='ash'}
    }
}

这种方式就像一些框架加载配置文件

2、懒汉模式:延迟创建对象

2.1、线程不安全(适用于单线程)
/**
 * @author luojianhui
 * @date 2018/11/2
 */
public class Singleton4 {
    //静态变量保存唯一实例
    private static Singleton4 singleton;

    private Singleton4() {

    }

    public static Singleton4 getInstance() {
        if (singleton == null) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            singleton = new Singleton4();
        }
        return singleton;
    }
}

测试:

/**
 * @author luojianhui
 * @date 2018/9/12
 */
public class TestDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建线程
        Callable<Singleton4> callable = new Callable<Singleton4>() {
            @Override
            public Singleton4 call() throws Exception {
                return Singleton4.getInstance();
            }
        };
        //创建两个线程池
        ExecutorService es = Executors.newFixedThreadPool(2);
        Future<Singleton4> f1 = es.submit(callable);
        Future<Singleton4> f2 = es.submit(callable);

        Singleton4 singleton4 = f1.get();
        Singleton4 singleton41 = f2.get();

        System.out.println(singleton4 == singleton41);
        //输出结果:false
        es.shutdown();
    }
}

原因:当一个线程进入休眠,另一个线程此时判断singleton为null,两个线程都执行了if语句,所有创建了两个不能的实例

2.2、线程安全(适用于多线程)
/**
 * @author luojianhui
 * @date 2018/11/2
 */
public class Singleton5 {
    //静态变量保存唯一实例
    private static Singleton5 singleton;

    private Singleton5() {

    }

    public static Singleton5 getInstance() {
        //使用类作为锁对象
        synchronized (Singleton5.class) {
            if (singleton == null) {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                singleton = new Singleton5();
            }
            return singleton;
        }
    }
}
锁
2.3、静态内部类形式(适用于多线程)
/**
 * @author luojianhui
 * @date 2018/11/2
 * 在内部类被加载和初始化时,才创建实例对象
 * 静态内部类不会自动随着外部类的加载和初始化而初始化,他是要单独去加载和初始化的
 * 因为是在内部类加载和初始化时创建的,因此是线程安全的
 */
public class Singleton6 {
    private Singleton6() {
    }

    private static class Inner {
        private static final Singleton6 SINGLETON_6 = new Singleton6();
    }

    public static Singleton6 getInstance() {
        return Inner.SINGLETON_6;
    }
}

版权声明:本文为laoash原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/laoash/p/9897497.html