单例模式
饿汉式
/** * 饿汉式 * 类加载到内存后,就实例化一个单例,JVM保证线程安全 * 简单实用,推荐使用! * 唯一缺点:不管用到与否,类装载时就完成实例化 * Class.forName("") * (话说你不用的,你装载它干啥) */public class Mgr01 { private static final Mgr01 INSTANCE = new Mgr01(); private Mgr01() {}; public static Mgr01 getInstance() { return INSTANCE; } public void m() { System.out.println("m"); } public static void main(String[] args) { Mgr01 m1 = Mgr01.getInstance(); Mgr01 m2 = Mgr01.getInstance(); System.out.println(m1 == m2); }}
懒汉式
/** * lazy loading * 也称懒汉式 * 虽然达到了按需初始化的目的,但却带来线程不安全的问题 */public class Mgr03 { private static Mgr03 INSTANCE; private Mgr03() { } public static Mgr03 getInstance() { if (INSTANCE == null) { try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } INSTANCE = new Mgr03(); } return INSTANCE; } public void m() { System.out.println("m"); } public static void main(String[] args) { for(int i=0; i<100; i++) { new Thread(()-> System.out.println(Mgr03.getInstance().hashCode()) ).start(); } }}
/** * lazy loading * 也称懒汉式 * 虽然达到了按需初始化的目的,但却带来线程不安全的问题 * 可以通过synchronized解决,但也带来效率下降 */public class Mgr04 { private static Mgr04 INSTANCE; private Mgr04() { } public static synchronized Mgr04 getInstance() { if (INSTANCE == null) { try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } INSTANCE = new Mgr04(); } return INSTANCE; } public void m() { System.out.println("m"); } public static void main(String[] args) { for(int i=0; i<100; i++) { new Thread(()->{ System.out.println(Mgr04.getInstance().hashCode()); }).start(); } }}
/** * lazy loading * 也称懒汉式 * 虽然达到了按需初始化的目的,但却带来线程不安全的问题 * 可以通过synchronized解决,但也带来效率下降 */public class Mgr05 { private static Mgr05 INSTANCE; private Mgr05() { } public static Mgr05 getInstance() { if (INSTANCE == null) { //妄图通过减小同步代码块的方式提高效率, //然后不可行--不可行的原因是instance=new SingletonDemo() //的几个步骤可能发生指令重排 synchronized (Mgr05.class) { try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } INSTANCE = new Mgr05(); } } return INSTANCE; } public void m() { System.out.println("m"); } public static void main(String[] args) { for(int i=0; i<100; i++) { new Thread(()->{ System.out.println(Mgr05.getInstance().hashCode()); }).start(); } }}
/** * lazy loading * 也称懒汉式 * 虽然达到了按需初始化的目的,但却带来线程不安全的问题 * 可以通过synchronized解决,但也带来效率下降 */public class Mgr06 { private static volatile Mgr06 INSTANCE; //JIT private Mgr06() { } public static Mgr06 getInstance() { if (INSTANCE == null) { //双重检查 synchronized (Mgr06.class) { if(INSTANCE == null) { try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } INSTANCE = new Mgr06(); } } } return INSTANCE; } public void m() { System.out.println("m"); } public static void main(String[] args) { for(int i=0; i<100; i++) { new Thread(()->{ System.out.println(Mgr06.getInstance().hashCode()); }).start(); } }}
静态内部类方式
/** * 静态内部类方式 * JVM保证单例 * 加载外部类时不会加载内部类,这样可以实现懒加载 */public class Mgr07 { private Mgr07() { } private static class Mgr07Holder { private final static Mgr07 INSTANCE = new Mgr07(); } public static Mgr07 getInstance() { return Mgr07Holder.INSTANCE; } public void m() { System.out.println("m"); } public static void main(String[] args) { for(int i=0; i<100; i++) { new Thread(()->{ System.out.println(Mgr07.getInstance().hashCode()); }).start(); } }}
enum枚举方式
/** * 不仅可以解决线程同步,还可以防止反序列化。 */public enum Mgr08 { INSTANCE; public void m() {} public static void main(String[] args) { for(int i=0; i<100; i++) { new Thread(()->{ System.out.println(Mgr08.INSTANCE.hashCode()); }).start(); } }}
单例模式反序列化漏洞测试
public class DeserializationTest { public static void main(String[] args) throws Exception { Mgr01 s1 = Mgr01.getInstance(); Mgr01 s2 = Mgr01.getInstance(); System.out.println(s1); System.out.println(s2); Class.forName("singleton.Mgr01"); /** * 单例模式反射漏洞測試 */ Class<?> clazz = Class.forName("singleton.Mgr01"); Constructor<Mgr01> c = (Constructor<Mgr01>) clazz.getDeclaredConstructor(null); c.setAccessible(true); Mgr01 s3 = c.newInstance(); Mgr01 s4 = c.newInstance(); System.out.println(s3); System.out.println(s4); }}
singleton.Mgr01@17e1886singleton.Mgr01@17e1886singleton.Mgr01@d1a2f1singleton.Mgr01@10e140b