编写单例模式的整体思路:
1.私有化构造方法
2.创建一个私有的关于自身的静态变量
3.创建一个获取自身实例的静态方法
A.饿汉模式
不能按需加载是饿汉模式的唯一缺点(歪歪:如果不加载,我写他干啥呢。。)
/**
* 饿汉模式
* 缺点:随类一起加载,用不到也加载
*/
public class Singleton_01 {
// 1.私有化构造方法
private Singleton_01(){}
// 2.创建静态实例
private static Singleton_01 singleton01 = new Singleton_01();
// 3.创建获取实例的静态方法
public static Singleton_01 getInstance(){
return singleton01;
}
}
B.懒汉模式——单线程模式
/**
* 懒汉模式(线程不安全)
* 优点:按需创建
* 缺点:线程不安全
*/
public class Singleton_02 {
// 1.私有化构造方法
private Singleton_02(){}
// 2.创建静态实例,但不初始化
private static Singleton_02 singleton02;
// 3.创建获取实例的静态方法
public static Singleton_02 getInstance(){
// 3.1判断对象是否存在
if (singleton02 == null){
// 线程A执行到这儿停住了,线程B执行到这儿继续向下执行了
// 当线程A再回来的时候,就又执行了一次
singleton02 = new Singleton_02();
}
return singleton02;
}
}
C.懒汉模式——线程安全
/**
* 懒汉模式(线程安全)
* 优点:按需加载,线程安全
* 缺点:排队,效率低,相当于串行
*/
public class Singleton_03 {
//1.私有化构造方法
private Singleton_03(){}
//2.创建私有的静态变量,但不初始化
private static Singleton_03 singleton03;
//3.创建获取对象的静态同步方法
public static synchronized Singleton_03 getInstance(){
//3.1判断对象是否存在
if (singleton03 == null){
singleton03 = new Singleton_03();
}
return singleton03;
}
}
D.懒汉模式——双重校验
/**
*懒汉模式(双重校验)
*优点:按需加载,线程安全,提升部分性能
*/
public class Singleton_04 {
//1.私有化构造方法
private Singleton_04(){}
//2.创建私有静态变量
private volatile static Singleton_04 singleton04;
//3.创建获取对象的方法
public static Singleton_04 getInstance(){
//3.1判断对象是否存在
if (singleton04 == null){
//3.1.1不存在时竞争锁,此时会出现,
//线程A执行到这里等待锁,线程B执行到这里获得锁
synchronized (Singleton_04.class){
// 3.1.2再次校验是否存在,为避免3.1.1此处需再次判断对象是否存在
//线程A执行到这里时,线程B必然已经执行完了
if (singleton04 == null){
// 3.1.3实例化对象,此处可能会出现jvm指令重排序的问题,
// 因此需要在变量前加volatile
singleton04 = new Singleton_04();
}
}
}
return singleton04;
}
}
E.懒汉模式——静态内部类
/**
* 懒汉模式——静态内部类
* 静态内部类是线程安全的,因为静态内部类也是按需加载,且只加载一次,是由JVM保证的
* 静态内部类中的静态变量会随内部类的加载而加载,且只加载一次
*/
public class Singleton_05 {
//1.私有化构造方法
private Singleton_05(){}
private static class SingletonHolder{
//2.创建私有的关于自身的静态变量
private static Singleton_05 singleton05 = new Singleton_05();
}
//3.创建获取自身的静态方法
public static Singleton_05 getInstance(){
return SingletonHolder.singleton05;
}
}
总结:
如何创建单例模式,最基本的思路我觉得是在于让对象只实例化一次,而为一次提供保障的,有锁,还有类加载。