单例模式


优缺点及使用场景

使用场景

  • 全局统一使用的配置类

  • 线程池

  • 方便多个线程直接之间通信的类

  • 数据库连接池

设计要点

  • 约束只有一个实力,外面不能随意的创建:构造器私有化

  • 保存实例:用静态变量保存

  • 为外面提供此实力:用get方法

饿汉式-懒汉式

饿汉式

饿汉式不存在线程安全的问题

最简单

public class Singleton1 {

    // 私有化构造方法,其他人无法创建实例
    private Singleton1(){};

    // 外部可以访问
    public static final Singleton1 SINGLETON = new Singleton1();

}

枚举

// 饿汉式-枚举类型 单例模式
public enum Singleton2 {

    INSTANCE

}

调用

public class TestMain {
    public static void main(String[] args) {
        Singleton2 singleton2 = Singleton2.INSTANCE;
        System.out.println(singleton2);
    }
}

静态代码块

当有属性需要初始化时

// 饿汉式-静态代码块类型 单例模式
public class Singleton3 {
    private Singleton3(){};

    public static final Singleton3 INSTANCE ;

    static{
        INSTANCE= new Singleton3();
    }
}

静态代码块

加载配置文件

import java.io.IOException;
import java.util.Properties;

// 饿汉式-静态代码块类型 单例模式
public class Singleton3 {
    private Singleton3(){};
    private String info;
    private Singleton3(String info){
        this.info = info;
    }
    public static final Singleton3 INSTANCE ;
    static{
        try {
            Properties properties = new Properties();
            properties.load(Singleton3.class.getClassLoader().getResourceAsStream("single.properties"));
            INSTANCE= new Singleton3(properties.getProperty("info"));

        } catch (IOException e) {
            throw  new RuntimeException();
        }
    }

    public String getInfo() {
        return info;
    }

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

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

懒汉式

单线程

存在线程安全问题

// 懒汉式,延迟创建实例对象
public class Singleton4 {
    private static Singleton4 instance;
    private Singleton4(){};
    public static Singleton4 getInstance() throws InterruptedException {
        if (null == instance){
            Thread.sleep(100);
            instance = new Singleton4();
        }
        return instance;
    }
}

测试

import java.util.concurrent.*;
public class TestMain {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Callable<Singleton4> c = new Callable<Singleton4>() {
            @Override
            public Singleton4 call() throws Exception {
                return Singleton4.getInstance();
            }
        };
        ExecutorService ex = Executors.newFixedThreadPool(2);
        Future<Singleton4> f1 = ex.submit(c);
        Future<Singleton4> f2 = ex.submit(c);
        Singleton4 s1 = f1.get();
        Singleton4 s2 = f2.get();
        System.out.println(s1);
        System.out.println(s2);
    }
}

线程安全版

// 懒汉式,延迟创建实例对象
public class Singleton5 {
    private static Singleton5 instance;
    private Singleton5(){};
    public static Singleton5 getInstance() throws InterruptedException {
        if (null == instance){
            synchronized(Singleton5.class){
                if (null == instance){
                    Thread.sleep(100);
                    instance = new Singleton5();
                }
            }
        }
        return instance;
    }
}

内部类

// 懒汉式,延迟创建实例对象
public class Singleton6 {

    private Singleton6(){};

    // 静态内部类不会随着外部类的初始化而初始化。
    // 当用这个类的时候才会加载初始化
    public static class Inner{
        private static final Singleton6 INSTANCE = new Singleton6();
        public static Singleton6 getInstance(){
            return INSTANCE;
        }
    }
}

文章作者: 张一雄
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 张一雄 !
  目录