zoukankan      html  css  js  c++  java
  • java 单例模式之线程安全的饿汉模式和懒汉模式

    转载博主:thankyou

    https://blog.csdn.net/twj13162380953/article/details/53869983

    理解:

    饿汉式获取实例的步骤简单所以线程更安全。懒汉式只是不会在类加载时即创建静态对象而效率略高,而因此也导致有判断是否已创建对象环节会使线程变得不安全,需要加同步锁才能解决该问题。

    单例模式

    解决的问题:保证一个类在内存中的对象唯一性.

    比如:多程序读取一个配置文件时,建议配置文件封装成对象。会方便操作其中数据,又要保证多个程序读到的是同一个配置文件对象,

    就需要该配置文件对象在内存中是唯一的。

    如何保证对象唯一性呢?
    思想:
    1,不让其他程序创建该类对象。
    2,在本类中创建一个本类对象。
    3,对外提供方法,让其他程序获取这个对象。

    步骤:
    1,因为创建对象都需要构造函数初始化,只要将本类中的构造函数私有化,其他程序就无法再创建该类对象;
    2,就在类中创建一个私有并静态的本类的对象
    3,定义一个方法,返回该对象,让其他程序可以通过方法就得到本类对象。(作用:可控)

    代码体现:
    1,私有化构造函数;
    2,创建私有并静态的本类对象;
    3,定义公有并静态的方法,返回该对象。

    饿汉模式:

    1.  
      class Single{
    2.  
      private Single(){} //私有化构造函数。
    3.  
      private static Single s = new Single(); //创建私有并静态的本类对象。
    4.  
      public static Single getInstance(){ //定义公有并静态的方法,返回该对象。
    5.  
      return s;
    6.  
      }
    7.  
      }

    //懒汉式:延迟加载方式。使用到的时候才回去初始化该对象

    1.  
      class Single2{
    2.  
      private Single2(){}
    3.  
      private static Single2 s = null;
    4.  
      public static Single2 getInstance(){
    5.  
      if(s==null)
    6.  
      s = new Single2();
    7.  
      return s;
    8.  
      }
    9.  
      }

    在多线程模式中,考虑到性能和线程安全问题,我们一般会选择下面两种比较经典的单例模式,在性能提高的同时,又保证了线程的安全.

    1.static inner Class

    2.dubble check instance

    (饿汉模式)static inner Class-内部静态类的形式

    1.  
      public class Singletion {
    2.  
       
    3.  
      private static class InnerSingletion {
    4.  
      private static Singletion single = new Singletion();
    5.  
      }
    6.  
       
    7.  
      public static Singletion getInstance(){
    8.  
      return InnerSingletion.single;
    9.  
      }
    10.  
       
    11.  
      }



    (懒汉模式) dubble check instance-为确保线程安全,需要两次check

    1.  
      public class DubbleSingleton {
    2.  
       
    3.  
      private static DubbleSingleton ds;
    4.  
       
    5.  
      public static DubbleSingleton getDs(){
    6.  
      if(ds == null){
    7.  
      try {
    8.  
      //模拟初始化对象的准备时间...
    9.  
      Thread.sleep(3000);
    10.  
      } catch (InterruptedException e) {
    11.  
      e.printStackTrace();
    12.  
      }
    13.  
      synchronized (DubbleSingleton.class) {
    14.  
      if(ds == null){
    15.  
      ds = new DubbleSingleton();
    16.  
      }
    17.  
      }
    18.  
      }
    19.  
      return ds;
    20.  
      }
    21.  
       
    22.  
      public static void main(String[] args) {
    23.  
      Thread t1 = new Thread(new Runnable() {
    24.  
      @Override
    25.  
      public void run() {
    26.  
      System.out.println(DubbleSingleton.getDs().hashCode());
    27.  
      }
    28.  
      },"t1");
    29.  
      Thread t2 = new Thread(new Runnable() {
    30.  
      @Override
    31.  
      public void run() {
    32.  
      System.out.println(DubbleSingleton.getDs().hashCode());
    33.  
      }
    34.  
      },"t2");
    35.  
      Thread t3 = new Thread(new Runnable() {
    36.  
      @Override
    37.  
      public void run() {
    38.  
      System.out.println(DubbleSingleton.getDs().hashCode());
    39.  
      }
    40.  
      },"t3");
    41.  
       
    42.  
      t1.start();
    43.  
      t2.start();
    44.  
      t3.start();
    45.  
      }
    46.  
       
    47.  
      }

    输出结果:

      1.  
        792363696
      2.  
        792363696
      3.  
        792363696
  • 相关阅读:
    一个tomcat设置多个端口,多个端口对应多个应用
    Docker 容器镜像删除
    Centos7上安装docker
    oracle锁表与解表
    windows共享文件夹
    tomcat部署项目后,war包是否可刪?war包存在必要性!
    解决Windows对JDK默认版本切换问题
    FLASHBACK介绍
    ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效
    Linux journalctl命令
  • 原文地址:https://www.cnblogs.com/ConfidentLiu/p/9468180.html
Copyright © 2011-2022 走看看