单例模式

mac2024-05-30  55

1. 什么是单例模式

  就是采取一定的方法保证在整个软件系统中,对某个类只存在一个实例对象,并且该类只提供一个取得其对象实例的方法。

1.1 作用

  保证在整个应用程序的声明周期中,任何一个时刻,单例类的实例都只存在一个(也可以不存在)。

1.2 设计要求

  单例类的构造函数必须为私有,同时单例类必须提供一个全局访问点。

1.3 单例模式UML图

1.4 使用场景

  需要频繁进行创建和销毁的对象;重量级对象。

2. 单例模式的实现

2.1 饿汉式(静态变量)
public class Singleton { //1.本类内部创建实例对象 private static final Singleton instance = new Singleton(); //2.将构造器私有化(防止外部new) private Singleton(){ } //提供一个公有静态方法,返回对象实例 public static Singleton getInstance(){ return instance; } }

优缺点说明:  1)写法简单;在类装载的时候就完成实例化,避免了线程同步问题。  2)在类装载的时候就实例化,没有达到懒加载的效果;如果没有使用这个类,会造成内存浪费。

2.2 饿汉式(静态代码块)
public class Singleton { //1.本类内部创建实例对象 private static Singleton instance ; static{ //在静态代码块中创建单例对象 instance = new Singleton(); } //2.将构造器私有化(防止外部new) private Singleton(){ } //提供一个公有静态方法,返回对象实例 public static Singleton getInstance(){ return instance; } }

优缺点说明:  缺点和优点与静态变量的饿汉式一样。可用,但是若创建出来的类没有使用时,会造成内存浪费。

2.3 懒汉式,不安全

  提供一个静态的公有方法,当需要获取对象实例时,采取创建该对象。

public class Singleton { private static Singleton instance; private Singleton(){ } public static Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }

优缺点说明:  1)起到了懒加载效果,在单线程下可用;  2)如果在多线程下,一个线程进入了if(instance==null)判断语句块,在还没来得及往下执行的时候,另一个线程也通过了这个语句块,就会创建多个实例对象。  3)在实际开发中,建议不要使用。

2.4 懒汉式(线程安全,同步方法)
public class Singleton { private static Singleton instance; private Singleton(){ } public static synchronized Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }

优缺点说明:  1)线程安全;  2)效率低。每个线程在想获取对象实例的时候,执行getInstance()方法都需要进行同步,而其实这个方法只执行一次实例化代码就够了,后面想要获得实例对象,只需要return即可。  3)可用,但不推荐。

2.5 双重检查
public class Singleton { private static Singleton instance; private Singleton(){ } public static synchronized Singleton getInstance(){ if(instance==null){//为了避免不必要的同步 synchronized(Singleton.class){ if(instance==null){//在null情况下创建实例 instance = new Singleton(); } } } return instance; } }

优缺点说明:  1)线程安全,延迟加载,效率高。实例化代码只执行一次,后面再访问时,判断if(instance==null),直接return,而不进入if语句块,避免了反复创建实例化对象。  2)再实际开发中,推荐使用。

2.6 静态内部类的方式
public class Singleton { private Singleton(){ } public static Singleton getInstance(){ return Inner.instance; } private static class Inner{ private static final Singleton instance = new Singleton(); } }

优缺点说明:  1)采用类加载机制来保证初始化时只有一个线程;  2)静态内部类方式在Singleton类被装载时不会立即被实例化,而是在执行了getInstance()方法后,才会创建实例对象;  3)类的静态属性定义为static final,它只会在第一个加载类时初始化而不能被修改,从而保证了线程的安全性;  4)避免了线程不安全,效率高,实现了延迟加载;  5)推荐使用。

2.7 枚举方式
public class Singleton { public static void main(String[] args){ Method instance01 = Method.INSTANCE; Method instance02 = Method.INSTANCE; System.out.println(instance01==instance02); //true说明是同一个对象 instance01.work(); } } enum Method{ INSTANCE; //一个属性,保证他是一个单例 public void work(){ System.out.println("run"); } }

优缺点说明:  1)不仅能避免多线程同步问题,还能防止反序列化创建新对象;  2)推荐使用。

最新回复(0)