1)饿汉式单例模式
package Singleton; public class Singleton01 { public static void main(String[] args) { Singleton instance = Singleton.getInstance(); System.out.println(instance); } } class Singleton{ private Singleton(){ } private final static Singleton instance = new Singleton(); public static Singleton getInstance(){ return instance; } }
优点:写法简单,类加载的时候就完成了实例化,避免了线程同步的问题
缺点:在类加载的阶段完成了实例化,如果从始至终一直没有用到,就会造成浪费
2)饿汉式静态代码块写法
package Singleton; public class Singleton02 { public static void main(String[] args) { Singleton instance = Singleton.getInstance(); System.out.println(instance); } } class Singleton2{ private Singleton2(){ } private static Singleton2 instance ; static{ instance = new Singleton2(); } public static Singleton2 getInstance(){ return instance; } }
3)懒汉式写法(线程不安全)
优点:起到了Lazy Loading的效果
缺点:线程不安全,实际开发中不推荐使用,有可能破坏单例模式的初衷
package Singleton; public class Singleton03 { public static void main(String[] args) { Singleton3 instance = Singleton3.getInstance(); System.out.println(instance); } } class Singleton3{ private static Singleton3 instance; private Singleton3(){ } public static Singleton3 getInstance(){ if(instance==null){ instance = new Singleton3(); } return instance; } }
4)懒汉式写法(线程安全)
package Singleton; public class Singleton03 { public static void main(String[] args) { Singleton3 instance = Singleton3.getInstance(); System.out.println(instance); } } class Singleton3{ private static Singleton3 instance; private Singleton3(){ } public synchronized static Singleton3 getInstance(){ if(instance==null){ instance = new Singleton3(); } return instance; } }
优点:解决了线程不安全的问题
缺点:效率太低了,不推荐使用
5)双重检查
package Singleton; public class Singleton04 { public static void main(String[] args) { Singleton4 instance = Singleton4.getInstance(); System.out.println(instance); } } class Singleton4{ private static volatile Singleton4 instance; private Singleton4(){ } public static Singleton4 getInstance(){ if(instance==null){ synchronized (Singleton4.class){ if(instance==null){ instance = new Singleton4(); } } } return instance; } }
优点:
有了volatile关键字,就可以保证线程安全
实例化代码只有一次,避免违背单例模式
延迟加载,效率较高
在实际开发中,推荐使用这种单例设计模式
6)静态内部类
为什么使用静态内部类:当类被加载的时候,静态内部类里面,是不会被装载的
package Singleton; //利用静态内部类进行初始化 public class Singleton05 { public static void main(String[] args) { Singleton4 instance = Singleton4.getInstance(); System.out.println(instance); } } class Singleton5{ private static volatile Singleton instance; private Singleton5(){} private static class Singleton5Instance{ private static final Singleton5 INSTANCE = new Singleton5(); } public static synchronized Singleton5 getInstance(){ return Singleton5Instance.INSTANCE; } }
优点:
这种方式采用了类加载的机制来保证初始化实例时只有一个线程
静态内部类在Singleton类被加载时,不会被立即实例化,而是在需要实例化时,调用getInstance方法,才会装载SingletonInstance,从而完成Singleton的实例化
类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的
优点:避免了线程不安全的问题,利用静态内部类特点实现延迟加载,效率高
推荐使用!