单例模式
单例设计模式,即某个类在整个系统中只能有一个实例对象,例如JVM运行环境的Runtime
类就是单例
要想保证一个类只有一个实例,通过将构造器私有化来实现
这个类还必须通过构造器自行创建这个实例,可以用该类的静态变量来保存这个唯一的实例
通过直接暴露或者get方法获取静态变量的方式对外提供获取该实例对象
常见形式
饿汉式:在类初始化的时候直接创建对象,不存在线程安全问题
直接实例化饿汉式
public class Singleton {
//内存自行创建实例对象,使用静态变量保存
//public 通过类名向外直接暴露
public static final Singleton INSTANCE = new Singleton();
//构造器私有化
private Singleton(){
}
//还可以通过get方法对外提供实例对象
public static Singleton getINSTANCE() {
return INSTANCE;
}
}
枚举式,该类型的对象个数是有限的,如果限定为一个,就成为了单例模式
public enum Singleton {
//限定只有一个对象
INSTANCE
}
静态代码块,常用于在创建对象之前,需要在静态代码块中初始化一些其它配置文件数据
public class Singleton {
public static final Singleton INSTANCE;
//静态代码块创建实例对象,
static {
INSTANCE = new Singleton();
}
private Singleton2(){
}
}
懒汉式:延迟创建对象
线程不安全的实现方法,只适合于单线程
public class Singleton {
//private 只能通过get方法获取
private static Singleton instance;
private Singleton() {
}
//调用get方法的时候才会创建实例对象
public static Singleton getInstance() {
//如果之前没有创建过就创建对象,如果之前已经创建过,就直接返回之前创建的实例对象
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
如果多线程,使用synchronized
需要保证线程安全
public class Singleton {
//private 只能通过get方法获取
private static Singleton instance;
private Singleton() {
}
//调用get方法的时候才会创建实例对象
public static Singleton getInstance() {
//如果之前没有创建过就创建对象,如果之前已经创建过,就直接返回之前创建的实例对象
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
return instance;
}
}
为了避免所有的线程都在等待获取锁,可以优化一下性能,在获取锁之前先判断一下实例对象是否已经创建出来了,如果之前没有创建实例对象,就等待获取锁,如果已经创建出来了,之后的线程无需再等待获取锁,直接就返回之前创建出来的实例对象
if (instance == null) {
synchronized (Singleton3.class) {
if (instance == null) {
instance = new Singleton3();
}
}
}
还可以通过内部类创建实例对象的方式,实现延迟创建,而且还保证的线程安全。静态内部类不会自动随着外部类的加载和初始化而初始化,需要单独加载和初始化
public class Singleton4 {
private Singleton4() {
}
//当调用get方法的时候,内部类才会被加载和初始化,实现延迟创建实例对象
private static class Inner{
private static final Singleton4 instance = new Singleton4();
}
public static Singleton4 getInstance() {
return Inner.instance;
}
}