【单例模式】饿汉式,懒汉式?JAVA如何实现单例?线程安全吗?

简介: 【单例模式】饿汉式,懒汉式?JAVA如何实现单例?线程安全吗?


Java单例设计模式

  • 单例设计模式(Singleton):单例即唯一实例,某个类在整个系统中只能有一个实例对象可被获取和使用的代码模式。(例如:代表JVM运行环境的Runtime类)


要点

  • ①某个类只能有一个实例。
  • 构造器私有化。
  • ②这个类必须自行创建这个实例。
  • 含有一个该类的静态变量来保存这个唯一的实例。
  • ③这个类必须自行向整个系统提供这个实例。
  • 对外提供获取该实例的方式:
  1. 直接暴露
  2. 用静态变量的get方法获取


饿汉式

  • 饿汉式:直接创建对象,不存在线程安全问题。(在类初始化时直接创建对象,不管你是否需要这个对象都会创建)
  • 实现方式:
  • 直接实例化饿汉式(简洁明了)
  • 枚举式(最简洁)
  • 静态代码块饿汉式(适合复杂实例化)


  1. 直接实例化
//Singleton:单例设计模式,软件开发中常见的设计模式之一
//单例设计模式——饿汉式1:直接实例化饿汉式
/*
 * 1.构造器私有化
 * 2.自行创建,并且用静态变量保存
 * 3.向外提供这个实例
 * 4.使用final修饰,强调这是一个单例
 */
public class Singleton_hungry1 {
  //直接实例化
  private static final Singleton_hungry1 INSTANCE = new Singleton_hungry1();
  //构造器私有化
  private Singleton_hungry1(){}
}


  1. 枚举式
/**
 * 枚举类型:表示该类型的变量是有限的几个
 * 我们可以限定为一个,从而成了单例
 *
 */
public enum Singleton_hungry2 {
  //枚举类型的实例
  INSTANCE;
  private Singleton_hungry2() {}
}


  1. 静态代码块
public class Singleton_hungry3 {
  public static final Singleton_hungry3 INSTANCE;
  static {
    //复杂情况在静态代码块中解决
    INSTANCE = new Singleton_hungry3();
  }
  private Singleton_hungry3() {}
}


懒汉式

  • 懒汉式:延迟创建对象。
  • 实现方式:
  • 线程不安全(适用于单线程)
  • 线程安全(适用于多线程)
  • 静态内部类形式(适用于多线程)
  1. 线程不安全
/*
 * 懒汉式:延迟创建这个实例对象
 * 1. 构造器私有化
 * 2.用一个静态变量保存唯一实例
 * 3.提供一个静态方法,用于获取实例*/
public class Singleton4 {
  private static Singleton4 instance;
  private Singleton4() {}
  //线程不安全
  public static Singleton4 getInstance() {
    if(instance == null) {
      instance = new Singleton4();
    }
    return instance;
  }
}


  1. 线程安全
public class Singleton5 {
  private static Singleton5 instance;
  private Singleton5() {}
  public static Singleton5 getInstance() {
    //上锁、线程安全
    synchronized(Singleton5.class){
      if(instance == null) {
        instance = new Singleton5();
      }
    }
    return instance;
  }
}


  1. 静态内部类形式
/*
 * 懒汉式:延迟创建这个实例对象
 * 1. 构造器私有化
 * 2.用一个静态变量保存唯一实例
 * 3.提供一个静态方法,用于获取实例*/
public class Singleton6 {
  private Singleton6() {}
  //内部类:静态内部类不会随着外部类的加载和初始化而初始化,它是要单独去加载和初始化的
  //唯一实例因为是在内部类加载和初始化时才创建的,所以线程安全
  private static class inner{
    //唯一实例: 在内部类被加载和初始化时才被创建
    private static Singleton6 instance = new Singleton6();
  }
  public static Singleton6 getInstance() {
    return inner.instance;
  }
}




目录
相关文章
|
1天前
|
Java
Java一分钟:线程协作:wait(), notify(), notifyAll()
【5月更文挑战第11天】本文介绍了Java多线程编程中的`wait()`, `notify()`, `notifyAll()`方法,它们用于线程间通信和同步。这些方法在`synchronized`代码块中使用,控制线程执行和资源访问。文章讨论了常见问题,如死锁、未捕获异常、同步使用错误及通知错误,并提供了生产者-消费者模型的示例代码,强调理解并正确使用这些方法对实现线程协作的重要性。
9 3
|
1天前
|
安全 算法 Java
Java一分钟:线程同步:synchronized关键字
【5月更文挑战第11天】Java中的`synchronized`关键字用于线程同步,防止竞态条件,确保数据一致性。本文介绍了其工作原理、常见问题及避免策略。同步方法和同步代码块是两种使用形式,需注意避免死锁、过度使用导致的性能影响以及理解锁的可重入性和升级降级机制。示例展示了同步方法和代码块的运用,以及如何避免死锁。正确使用`synchronized`是编写多线程安全代码的核心。
17 2
|
1天前
|
安全 Java 调度
Java一分钟:多线程编程初步:Thread类与Runnable接口
【5月更文挑战第11天】本文介绍了Java中创建线程的两种方式:继承Thread类和实现Runnable接口,并讨论了多线程编程中的常见问题,如资源浪费、线程安全、死锁和优先级问题,提出了解决策略。示例展示了线程通信的生产者-消费者模型,强调理解和掌握线程操作对编写高效并发程序的重要性。
13 3
|
1天前
|
安全 Java
深入理解Java并发编程:线程安全与性能优化
【5月更文挑战第11天】在Java并发编程中,线程安全和性能优化是两个重要的主题。本文将深入探讨这两个方面,包括线程安全的基本概念,如何实现线程安全,以及如何在保证线程安全的同时进行性能优化。我们将通过实例和代码片段来说明这些概念和技术。
2 0
|
1天前
|
Java 调度
Java并发编程:深入理解线程池
【5月更文挑战第11天】本文将深入探讨Java中的线程池,包括其基本概念、工作原理以及如何使用。我们将通过实例来解释线程池的优点,如提高性能和资源利用率,以及如何避免常见的并发问题。我们还将讨论Java中线程池的实现,包括Executor框架和ThreadPoolExecutor类,并展示如何创建和管理线程池。最后,我们将讨论线程池的一些高级特性,如任务调度、线程优先级和异常处理。
|
2天前
|
安全 Java
【JAVA进阶篇教学】第十篇:Java中线程安全、锁讲解
【JAVA进阶篇教学】第十篇:Java中线程安全、锁讲解
|
2天前
|
安全 Java
【JAVA进阶篇教学】第六篇:Java线程中状态
【JAVA进阶篇教学】第六篇:Java线程中状态
|
2天前
|
缓存 Java
【JAVA进阶篇教学】第五篇:Java多线程编程
【JAVA进阶篇教学】第五篇:Java多线程编程
|
3天前
|
Java 数据库
【Java多线程】对线程池的理解并模拟实现线程池
【Java多线程】对线程池的理解并模拟实现线程池
12 1
|
3天前
|
设计模式 消息中间件 安全
【Java多线程】关于多线程的一些案例 —— 单例模式中的饿汉模式和懒汉模式以及阻塞队列
【Java多线程】关于多线程的一些案例 —— 单例模式中的饿汉模式和懒汉模式以及阻塞队列
9 0