Singleton:在Java中即指单例设计模式,它是软件开发中最常用的设计模式之一。
单:指唯一
例:指实例
单例设计模式,即某个类在整个系统中只能有一个实例对象可被获取和使用的代码模式。
要点:
一、单例类只能有一个实例
- 保证构造器私有化(防止通过构造器实例化)
二、单例类必须自信创建这个实例
- 在单例类中创建一个静态变量来保存这个唯一的实例
三、单例类必须自行向整个系统提供这个实例
- 对外提供该实例对象的获取方式
- 直接暴露该实例对象
- 用静态变量的get方法获取该实例对象
单例的几种常见形式
饿汉式:直接创建对象,不存在线程安全问题
- 直接实例化饿汉式(简介直观)
1 /** 2 * 单例饿汉式一(1) 3 * 直接实例化饿汉式(简洁直观) 4 * 对外提供获取该实例对象的方式: 5 * (1)直接暴露 6 * (2)用静态变量的get方法获取 7 */ 8 public class SingletonHungry1 { 9 10 public static final SingletonHungry1 INSTANCE = new SingletonHungry1(); 11 12 private SingletonHungry1() {} 13 } 14 15 16 /** 17 * 单例饿汉式一(2) 18 * 直接实例化饿汉式(简洁直观) 19 * 对外提供获取该实例对象的方式: 20 * (1)直接暴露 21 * (2)用静态变量的get方法获取 22 */ 23 public class SingletonHungry2 { 24 25 private static final SingletonHungry2 INSTANCE = new SingletonHungry2(); 26 27 private SingletonHungry2() {} 28 29 public static SingletonHungry2 getInstance() { 30 return INSTANCE; 31 } 32 }
- 枚举式(最简洁)
1 /** 2 * 单例饿汉式二 3 * 枚举式(最简洁) 4 */ 5 public enum SingletonHungry3 { 6 INSTANCE 7 }
- 静态代码块饿汉式(适合复杂实例化)
1 /** 2 * 单例饿汉式三 3 * 静态代码块饿汉式(适合复杂实例化) 4 */ 5 public class SingletonHungry4 { 6 7 public static final SingletonHungry4 INSTANCE; 8 9 private String info; 10 11 static { 12 // 这里用来实现复杂的实例化 13 // ......复杂代码 14 try { 15 Properties pro = new Properties(); 16 pro.load(SingletonHungry4.class.getClassLoader().getResourceAsStream("singleton.properties")); 17 INSTANCE = new SingletonHungry4(pro.getProperty("info")); 18 } catch (IOException e) { 19 throw new RuntimeException(e); 20 } 21 } 22 23 private SingletonHungry4(String info) { 24 this.info = info; 25 } 26 }
懒汉式:延迟创建对象
- 线程不安全(适用于单线程)
1 /** 2 * 单例懒汉式一 3 * 线程不安全(适用于单线程) 4 */ 5 public class SingletonLazy1 { 6 7 private static SingletonLazy1 INSTANCE; 8 9 private SingletonLazy1() {} 10 11 public static SingletonLazy1 getInstance() { 12 if (INSTANCE == null) { 13 try { 14 Thread.sleep(100); 15 } catch (InterruptedException e) { 16 e.printStackTrace(); 17 } 18 INSTANCE = new SingletonLazy1(); 19 } 20 return INSTANCE; 21 } 22 }
- 线程安全(适用于多线程)
1 /** 2 * 单例懒汉式二(1) 3 * 线程安全(适用于多线程) 4 */ 5 public class SingletonLazy2 { 6 7 private static SingletonLazy2 INSTANCE; 8 9 private SingletonLazy2() {} 10 11 public static SingletonLazy2 getInstance() { 12 synchronized (SingletonLazy2.class) { 13 if (INSTANCE == null) { 14 try { 15 Thread.sleep(100); 16 } catch (InterruptedException e) { 17 e.printStackTrace(); 18 } 19 INSTANCE = new SingletonLazy2(); 20 } 21 } 22 return INSTANCE; 23 } 24 } 25 26 /** 27 * 单例懒汉式二(2) 28 * 线程安全(适用于多线程,优化效率) 29 */ 30 public class SingletonLazy3 { 31 32 private static SingletonLazy3 INSTANCE; 33 34 private SingletonLazy3() {} 35 36 public static SingletonLazy3 getInstance() { 37 if (INSTANCE == null) { // 不等于空直接返回,提高效率 38 synchronized (SingletonLazy3.class) { 39 if (INSTANCE == null) { 40 try { 41 Thread.sleep(100); 42 } catch (InterruptedException e) { 43 e.printStackTrace(); 44 } 45 INSTANCE = new SingletonLazy3(); 46 } 47 } 48 } 49 50 return INSTANCE; 51 } 52 }
- 静态内部类形式(适用于多线程)
在内部类被加载和初始化时,才创建INSTANCE实例对象
静态内部类不会自动随着外部类的加载和初始化而初始化,它是要单独去加载和初始化的
因为是在内部类加载和初始化时创建的,因此是线程安全的
1 /** 2 * 单例懒汉式三 3 * 静态内部类(适用于多线程) 4 * 在内部类被加载和初始化时,才创建INSTANCE实例对象 5 * 静态内部类不会自动随着外部类的加载和初始化而初始化,它是要单独去加载和初始化的 6 * 因为是在内部类加载和初始化时,创建的,因此是线程安全的 7 */ 8 public class SingletonLazy4 { 9 10 private SingletonLazy4() {} 11 12 private static class Inner { 13 private static final SingletonLazy4 INSTANCE = new SingletonLazy4(); 14 } 15 16 public static SingletonLazy4 getInstance() { 17 return Inner.INSTANCE; 18 } 19 }
本文用于记录Singleton的学习,方便以后回顾!学完的东西容易忘,以文章的形式记录下来。欢迎大家学习和指出文章中的错误,谢谢!