Singleton单例模式
Singleton单例模式
Singleton:在Java中指单例模式,它是软件开发中常用的设计模式之一。
单例模式:即某个类在整个系统中只能有一个实例对象可被获取和使用的代码模式。
例如:代表JVM运行环境的Runtime类
要点
- 一个类只能有一个实例;
- 构造器私有化
- 它必须自行创建这个实例;
- 含有一个该类的静态变量来保存这个唯一的实例
- 必须自行向整个系统提供这个实例;
- 对外提供获取该实例对象的方法
- ①直接暴露 ②用静态变量的get方法获取
常见形式
饿汉式:在类初始化时,直接创建对象,不存在线程安全问题
-
直接实例化饿汉式(简洁直观)
/** * 饿汉式 * 在类初始化时,直接创建实例对象,不管你是否需要这个对象都会创建 * (1)构造器私有化 * (2)自行创建,并且用静态变量保存 * (3)向外提供这个实例 * (4)强调这是一个单例, 我们可以用final修改 */ public class Singleton1 { public static final Singleton1 INSTANCE = new Singleton1(); private Singleton1() { } }/** * 直接实例化饿汉式创建对象 */ @Test public void singleton1Test() { Singleton1 instance = Singleton1.INSTANCE; System.out.println(instance); //com.zt.Singleton1@51521cc1 //输出的是对象的类名+hashcode } -
枚举式(最简洁)
/** * 枚举类型。表示该类型的对象是有限的几个 * 我们可以限定为一个,就成了单例 */ public enum Singleton2 { INSTANCE }/** * 枚举式饿汉式创建对象 */ @Test public void singleton2Test() { Singleton2 instance = Singleton2.INSTANCE; System.out.println(instance); //INSTANCE 输出的是实例的名字 } -
静态代码块饿汉式(适合复杂实例化)
public class Singleton3 { public static final Singleton3 INSTANCE; private String info; public Singleton3(String info){ this.info = info; } static { try { //创建一个properties对象,用来获取properties配置文件中的属性 Properties pro = new Properties(); //加载配置文件 路径时从当前类的类加载器中获取的 pro.load(Singleton3.class.getClassLoader().getResourceAsStream("single.properties")); INSTANCE = new Singleton3(pro.getProperty("info")); } catch (IOException e) { //抛出运行时异常 throw new RuntimeException(e); } } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } @Override public String toString() { return "Singleton3{" + "info='" + info + '\'' + '}'; } }在src目录下创建一个配置文件
single.propertiesinfo = hello/** * 静态代码块饿汉式创建对象 */ @Test public void singleton3Test() { Singleton3 instance = Singleton3.INSTANCE; System.out.println(instance); //Singleton3{info='hello'} }
懒汉式:延迟创建对象
-
线程不安全(适用于单线程)
/** * 懒汉式:延迟创建这个实例对象 * (1)构造器私有化 * (2)用一个静态变量保存这个唯一的实例 * (3)提供一个静态方法,获取这个实例对象 */ public class Singleton4 { private static Singleton4 instance; private Singleton4() { } public static Singleton4 getInstance(){ if(instance==null){ instance = new Singleton4(); } return instance; } } -
线程安全(适用于多线程)
public class Singleton5 { private static Singleton5 instance; private Singleton5() { } public static Singleton5 getInstance() { if (instance == null) { synchronized (Singleton5.class) { if (instance == null) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } instance = new Singleton5(); } } } return instance; } } -
静态内部类形式(适用于多线程)
/** * 在内部类被加载和初始化时,才创建INSTANCE实例对象 * 静态内部类不会自动随着外部类的加载和初始化而初始化,它是要单独去加载和初始化的。 * 因为是在内部类加载和初始化时,创建的,因此是线程安全的 * / */ public class Singleten6 { private Singleten6() { } private static class Inner{ private static final Singleten6 INSTANCE = new Singleten6(); } public static Singleten6 getInstance(){ return Inner.INSTANCE; } }
小结:如果时饿汉式,枚举形式最简单,如果是懒汉式,静态内部类形式最简单;
两者最根本的区别时创建对象的时机,饿汉式不考虑线程安全(安全),懒汉式可以使用静态内部类形式或者用synchronized代码块实现线程安全。

浙公网安备 33010602011771号