设计模式-单例模式

104 阅读3分钟

一.单例模式有八种方式:

  1. 饿汉式(静态常量)

    特点:类加载就创建对象

代码:

public class SingletonTest01 {

  public static void main(String[] args) {
    Singleton instance1 = Singleton.getInstance();
    Singleton instance2 = Singleton.getInstance();
    System.out.print(instance1==instance2);
   }
}

class Singleton{
//构造器私有化
private Singleton(){}
//内部创建对象实例
private final static Singleton instance=new Singleton();
//对外提供对象实例
public static Singleton getInstance() {
    return instance;
  }
}

优点:1.类装载时完成类实例化,避免了线程安全问题。

缺点:1.类装载时完成类实例化,没有懒加载,如果没有用过造成内存资源浪费。

  1. 饿汉式(静态代码块)

代码:

public class SingletonTest02 {

public static void main(String[] args) {
    Singleton2 instance1 = Singleton2.getInstance();
    Singleton2 instance2 = Singleton2.getInstance();
    System.out.print(instance1==instance2);
   }
}

class Singleton2{
//构造器私有化
private Singleton2(){}
private  static Singleton2 instance;
static {
    //静态代码块加载时创建对象实例
    instance=new Singleton2();
}
//对外提供对象实例
public static Singleton2 getInstance() {
    return instance;
 }
} 

优缺点跟静态常量一样。

  1. 懒汉式(线程不安全)

    特点:当使用发现不存在才会创建对象,存在并发问题。

代码:

public class SingletonTest03 {
public static void main(String[] args) {
    Singleton3 instance1 = Singleton3.getInstance();
    Singleton3 instance2 = Singleton3.getInstance();
    System.out.println(instance1==instance2);
}
}
class Singleton3{
//构造器私有化
private Singleton3(){}

private  static Singleton3 instance;

//对外提供对象实例 
public static Singleton3 getInstance() {
    if(instance==null){
        instance=new Singleton3();
    }
    return instance;
 }
}

缺点:线程不安全,有概率存在相同对象。

  1. 懒汉式(线程安全,同步方法)

    特点:为了解决线程安全问题,加入同步代码器,但是效率低。

代码:

public class SingletonTest04 {
public static void main(String[] args) {
    Singleton4 instance1 = Singleton4.getInstance();
    Singleton4 instance2 = Singleton4.getInstance();
    System.out.println(instance1==instance2);
}
}

class Singleton4{
//构造器私有化
private Singleton4(){}

private  static Singleton4 instance;

//对外提供对象实例  加入同步关键字保证线程安全
public static synchronized Singleton4 getInstance() {
    if(instance==null){
        instance=new Singleton4();
    }
    return instance;
}
}

缺点:方法进行同步,效率太低。

  1. 懒汉式(线程安全,同步代码块)

    特点:为了降低锁力度,对创建对象进行线程同步。

代码:

public class SingletonTest05{
public static void main(String[] args) {
    Singleton5 instance1 = Singleton5.getInstance();
    Singleton5 instance2 = Singleton5.getInstance();
    System.out.println(instance1==instance2);
  }
}

class Singleton5{
//构造器私有化
private Singleton5(){}

private  static Singleton5 instance;

//对外提供对象实例  加入同步代码块解决 
public static synchronized Singleton5 getInstance() {
    if(instance==null){
        synchronized (Singleton5.class){
            instance=new Singleton5();
        }
    }
    return instance;
  }
}

缺点:仅仅对创建对象进行同步处理,对判断有无存在对象没做线程同步,并发问题依然存在。

  1. 双重检查

    特点:锁力度进一步缩小,对核心模块加锁,外围模块不加锁保证效率,加入volatile保证可见性和避免指令重拍

代码:

 public class SingletonTest06{
 public static void main(String[] args) {
    Singleton6 instance1 = Singleton6.getInstance();
    Singleton6 instance2 = Singleton6.getInstance();
    System.out.println(instance1==instance2);
  }
}

class Singleton6{
//构造器私有化
private Singleton6(){}
//对多个线程可见 防止指令重排
private static volatile Singleton6 instance;
//对外提供对象实例  加入同步代码块解决
public static synchronized Singleton6 getInstance() {
    //双重检查
    if(instance==null){
        synchronized (Singleton6.class){
            if(instance==null){
                instance=new Singleton6();
            }
        }
    }
    return instance;
  }
}

优点:线程安全;延迟加载;效率较高。

  1. 静态内部类

    特点:利用静态内部类和外部类装载时间不同实现懒加载;jvm装载类时线程安全

代码:

 public class SingletonTest07{
 
   public static void main(String[] args) {
     Singleton7 instance1 = Singleton7.getInstance();
     Singleton7 instance2 = Singleton7.getInstance();
     System.out.println(instance1==instance2);
  }
}


class Singleton7 {
//构造器私有化
private Singleton7(){}
//对多个线程可见 防止指令重排
private static volatile Singleton7 instance;

//静态内部类,该类有一个静态属性Singleton
private static class SingletonInstance{
    private static final Singleton7 INSTANCE=new Singleton7();
}

//装载Singleton7不会马上装载静态内部类SingletonInstance,同时调用getInstance()会装载SingletonInstance,jvm在装载类时线程安全
public static Singleton7 getInstance() {
    return SingletonInstance.INSTANCE;
  }
}

优点:线程安全;延迟加载;jvm类装载机制

  1. 枚举

    特点:防止反序列化重新创建对象

代码:

public class SingletonTest08 {
 public static void main(String[] args) {
    Singleton8 instance1 = Singleton8.INSTANCE;
    Singleton8 instance2 = Singleton8.INSTANCE;
    System.out.println(instance1==instance2);
  }
}

//使用枚举实现单例 防止反序列化重新创建对象
 enum Singleton8{
  INSTANCE;//属性
  public void say(){
    System.out.println("ok");
  }
}

优点:防止反序列化重新创建对象

JDK实例:

image.png