实现Singleton 模式–七种实现方式
public class Test02 {
/*单例模式,饿汉式,线程安全
*只要有先加载就让我吃,先写明私有的构造方法防止被new,然后九直接实例化,最后调用,不存在线程安全问题
* */
public static class Singleton01{
private static Singleton01 INSTANCE=new Singleton01();
private Singleton01() {
}
public static Singleton01 getInstance() {
return INSTANCE;
}
}
public static class Singleton2 {
/*单例模式,懒汉式,线程不安全
*饿了再找吃的,属于懒加载
*如果两个同时运行到判断instance是否为null的if语句,此时instance确实没有创建
*则两个线程都会创建一个实例
*
* */
private static Singleton2 instance = null;
private Singleton2() {
}
public static Singleton2 getInstance() {
if (instance == null) {
instance = new Singleton2();
}
return instance;
}
}
public static class Singleton3{
/*加锁懒汉模式,线程安全
* 大多时候这个锁占用的额外资源都浪费了,效率低
* */
private static Singleton3 instance;
public static synchronized Singleton3 getInstance(){
if(instance==null){
instance=new Singleton3();
}
return instance;
}
}
public static class Singleton4{
/*静态类内部加载,线程安全
*定义一个私有内部类tip1,在第一次用这个嵌套类时,会创建一格实例
*静态内部类不会再单例加载时就加载,而是在调用getInstance()方法时才进行加载
*由于私有属性,其他人无法使用SingletonHolder,
* */
private static class SingletonHolder{
private static Singleton4 instance=new Singleton4();
}
private static Singleton4 getInstance(){
return SingletonHolder.instance;
}
}
/*tip1:
私有内部类中可以使用外部类中所有的内容,包括私有的
私有内部类只能在外部类中可以通过对象使用私有内部类中的私有内容,其他类中不能使用
* */
enum Singleton5{
/*静态内部类,使用枚举方式,线程安全,无偿提供序列化机制,防止多次实例化
*
*调用Singleton5.INSTANCE.otherMethods();
* */
INSTANCE;
public void otherMethods(){
System.out.println("Something");
}
}
public static class Singleton6{
/*双重校验锁法tip2,通常安全
* */
private static Singleton6 instance;
private Singleton6(){
System.out.println("Singleton has loaded");
}
public static Singleton6 getInstance(){
if(instance==null){
synchronized(Singleton6.class){
if(instance==null){
instance=new Singleton6();
}
}
}
return instance;
}
}
/*tip2 并发模拟
* STEP 1. 线程A访问getInstance()方法,因为单例还没有实例化,所以进入了锁定块。
STEP 2. 线程B访问getInstance()方法,因为单例还没有实例化,得以访问接下来代码块,而接下来代码块已经被线程1锁定。
STEP 3. 线程A进入下一判断,因为单例还没有实例化,所以进行单例实例化,成功实例化后退出代码块,解除锁定。
STEP 4. 线程B进入接下来代码块,锁定线程,进入下一判断,因为已经实例化,退出代码块,解除锁定。
STEP 5. 线程A获取到了单例实例并返回,线程B没有获取到单例并返回Null
*/