写法1 懒汉式-线程不安全
懒汉式实现了懒加载,但是线程不安全,基本不会用到
public class Singleton1 {
public static Singleton1 singleton1;
public static Singleton1 getInstance() {
if (singleton1 == null) {
singleton1 = new Singleton1();
}
return singleton1;
}
}
写法2 懒汉式-线程安全
在第一种的基础上加了synchronized,保证线程安全,同时实现了懒加载,但是效率不高
public class Singleton2 {
public static Singleton2 singleton2;
public static synchronized Singleton2 getInstance() {
if (singleton2 == null) {
singleton2 = new Singleton2();
}
return singleton2;
}
}
写法3 饿汉式
由于实例优先提供,不存在线程安全问题,但是没有实现懒加载
public class Singleton3 {
public static Singleton3 singleton3 = new Singleton3();
public static Singleton3 getInstance() {
return singleton3;
}
}
写法4 饿汉式-变种
和上一种一样,只是将单例的创建挪到了静态块
public class Singleton4 {
public static Singleton4 singleton4;
static {
singleton4 = new Singleton4();
}
public static Singleton4 getInstance() {
return singleton4;
}
}
写法5 静态内部类式
静态内部类保证了懒加载,单例实例优先提供又保证了线程安全
public class Singleton5 {
private static class BuildSingleton {
private static Singleton5 singleton = new Singleton5();
}
public static final Singleton5 getInstance() {
return BuildSingleton.singleton;
}
}
写法6 枚举式
枚举的天然型保证了单例,天然的私有构造器,天然的线程安全性,未被大规模使用的原因是枚举出现的有点晚
public enum Singleton6 {
/**
* SINGLETON_6
*/
SINGLETON_6;
public void dosomething() {
}
}
写法7 双重校验锁式
1、volatile的使用是为了防止暴露一个未初始化的不完整单例实例
2、双重判空校验,第一个判断避免了频繁的加锁,第二个判断可以拦住创建多余实例的线程
3、加锁保证了线程安全
public class Singleton7 {
private volatile static Singleton7 singleton7;
public static Singleton7 getInstance() {
if (singleton7 == null) {
synchronized (Singleton7.class) {
if (singleton7 == null) {
singleton7 = new Singleton7();
}
}
}
return singleton7;
}
}