java优化之 单例模式的优化

白色玫瑰 程序猿

时间: 2023-07-11 阅读: 1 字数:9506

{}
该分类下的文章均为笔者阅读《Java程序性能优化》(葛一鸣)一书之所理解。如有欠缺,还请大佬们指点。

该分类下的文章均为笔者阅读《Java程序性能优化》(葛一鸣)一书之所理解。如有欠缺,还请大佬们指点。?

单例模式

单例模式用来创建的对象可以确保系统中只产生一个示例。主要有以下两种好处: 1.对于频繁使用的对象可以省略创建对象所花费的时间 2.由于new操作的次数减少,对系统内存的使用频率也会降低。将减轻GC压力。缩短GC停顿时间。

创建单例模式

public class SingleClassDemo {

   //第一种方式 直接创建对象 需要时直接返回
   public static SingleClassDemo sSingleClassDemo = new SingleClassDemo();

   private SingleClassDemo() {
      System.out.println("创建单例对象");
   }


   public static SingleClassDemo getInstance() {
      return sSingleClassDemo;
   }


   // 该类中的其他静态方法
   //public static String otherMethod() {
   //   return "otherMethod otherMethod!";
   //}

}

/**
*    测试类
*/
public class TestSingleClassDemo {
   @Test
   public void testInstance() {

      SingleClassDemo instance = SingleClassDemo.getInstance();
      System.out.println(instance);
      //打印结果:创建单例对象  top.wintp.demo.SingleClassDemo@50486d1d
   }
}
 

如上述代码就是单例模式的一种简单的实现方式。试想我们这种实现方式会有什么问题呢? 当该类中存在其他的静态方法的时候,我们直接调用该类的其他静态方法,也会创建该类的对象,这是我们不想得到的结果

调用示例:

public class TestSingleClassDemo {
   @Test
   public void testInstance() {
      //当调用该类的其他方法的时候,会初始化该类该类的静态变量 创建对象
      String string = SingleClassDemo.otherMethod();
      System.out.println(string);
      //打印结果:创建单例对象      cotherMethod otherMethod!
   }
}

单例模式优化一(懒加载模式)

修改创建单例对象的时机,当有需要的时候再去创建对象。


public class LazSingleClassDemo {

   private static LazSingleClassDemo mLazSingleClassDemo = null;

   private LazSingleClassDemo() {
      System.out.println("创建懒加载模式的对象");
   }

   public static LazSingleClassDemo getmLazSingleClassDemo() {

      if (mLazSingleClassDemo == null) {
         mLazSingleClassDemo = new LazSingleClassDemo();
      }

      return mLazSingleClassDemo;
   }

   public static String otherMehod() {

      return "otherMehod otherMehod";
   }
}



public class TestSingleClassDemo {
   @Test
   public void testInstance() {

      //   懒加载模式
      //在懒加载模式中 调用该类的其他方法并不会创建该类的对象
      String string = LazSingleClassDemo.otherMehod();
      System.out.println(string);
      //打印结果:otherMehod otherMehod
   }
}

当多线程并发时,懒加载模式就可能会出现,当前线程检测为null,第二个线程检测为null,同时创建两个对象的情况。那就违背了单例的原则。

调用示例:


public class TestSingleClassDemo {
   @Test
   public void testInstance() {
      //   懒加载模式的线程并发问题
      new Thread("t1") {
         public void run() {
            LazSingleClassDemo lazSingleClassDemo = LazSingleClassDemo.getmLazSingleClassDemo();
            System.out.println(this.getName());
            System.out.println(lazSingleClassDemo);
         }
      }.start();
      new Thread("t2") {
         public void run() {
            LazSingleClassDemo lazSingleClassDemo = LazSingleClassDemo.getmLazSingleClassDemo();
            System.out.println(this.getName());
            System.out.println(lazSingleClassDemo);
         }
      }.start();
      new Thread("t3") {
         public void run() {
            LazSingleClassDemo lazSingleClassDemo = LazSingleClassDemo.getmLazSingleClassDemo();
            System.out.println(this.getName());
            System.out.println(lazSingleClassDemo);
         }
      }.start();
      new Thread("t4") {
         public void run() {
            LazSingleClassDemo lazSingleClassDemo = LazSingleClassDemo.getmLazSingleClassDemo();
            System.out.println(this.getName());
            System.out.println(lazSingleClassDemo);
         }
      }.start();

      new Thread("t5") {
         public void run() {
            LazSingleClassDemo lazSingleClassDemo = LazSingleClassDemo.getmLazSingleClassDemo();
            System.out.println(this.getName());
            System.out.println(lazSingleClassDemo);
         }
      }.start();


      /*
        打印结果如下:
        
      创建懒加载模式的对象
      创建懒加载模式的对象
      t2
      top.wintp.demo.LazSingleClassDemo@475f260c
      t1
      top.wintp.demo.LazSingleClassDemo@55b9171e
      t3
      top.wintp.demo.LazSingleClassDemo@475f260c
      t4
      top.wintp.demo.LazSingleClassDemo@475f260c
      t5
      top.wintp.demo.LazSingleClassDemo@475f260c
       */
   }
}

单例模式优化二(懒加载模式线程并发问题)

使用同步方法避免多线程并发。


public class LazSingleSyncClassDemo {

   private static LazSingleSyncClassDemo mLazSingleClassDemo = null;

   private LazSingleSyncClassDemo() {
      System.out.println("创建懒加载模式同步方法的对象");
   }

    //使用synchronized 关键字
   public static synchronized LazSingleSyncClassDemo getmLazSingleClassDemo() {

      if (mLazSingleClassDemo == null) {
         mLazSingleClassDemo = new LazSingleSyncClassDemo();
      }

      return mLazSingleClassDemo;
   }

   public static String otherMethod() {

      return "otherMethod otherMethod";
   }
}

如上代码,再次进行多线程进行调用就不会出现创建多个对象的结果 线程安全避免不了的就是性能会降低。下面就是线程同步与线程不同的测试程序执行时长


public class TestSingleClassDemo {
   @Test
   public void testInstance() {
      long beginTime = System.currentTimeMillis();
      for (int i = 0; i < 100000; i++) {
         LazSingleClassDemo lazSingleClassDemo = LazSingleClassDemo.getmLazSingleClassDemo();
      }
      long endTime = System.currentTimeMillis();

      System.out.println(endTime - beginTime);
      //懒加载模式 不同步方法 用时间:   2


      beginTime = System.currentTimeMillis();
      for (int i = 0; i < 100000; i++) {
         LazSingleSyncClassDemo lazSingleClassDemo = LazSingleSyncClassDemo.getmLazSingleClassDemo();
      }
      endTime = System.currentTimeMillis();

      System.out.println(endTime - beginTime);
      //懒加载模式 同步方法 用时间:   5

   }
}


单例模式优化三(使用静态内部类进行优化)


public class EndSingleClassDemo {

   private static EndSingleClassDemo mLazSingleClassDemo = null;

   private EndSingleClassDemo() {
      System.out.println("创建懒加载模式的对象");
   }


   /**
    * 静态内部类
    */
   private static class EndSingleClassDemoHolder {
      private static EndSingleClassDemo mLazSingleClassDemo = new EndSingleClassDemo();
   }

   public static EndSingleClassDemo getmLazSingleClassDemo() {

      return EndSingleClassDemoHolder.mLazSingleClassDemo;
   }

   public static String otherMehod() {

      return "otherMehod otherMehod";
   }
}


public class TestSingleClassDemo {
   @Test
   public void testInstance() {
      new Thread("t1") {
         public void run() {
            EndSingleClassDemo endSingleClassDemo = EndSingleClassDemo.getmLazSingleClassDemo();
            System.out.println(this.getName());
            System.out.println(endSingleClassDemo);
         }
      }.start();
      new Thread("t2") {
         public void run() {
            EndSingleClassDemo endSingleClassDemo = EndSingleClassDemo.getmLazSingleClassDemo();
            System.out.println(this.getName());
            System.out.println(endSingleClassDemo);
         }
      }.start();
      new Thread("t3") {
         public void run() {
            EndSingleClassDemo endSingleClassDemo = EndSingleClassDemo.getmLazSingleClassDemo();
            System.out.println(this.getName());
            System.out.println(endSingleClassDemo);
         }
      }.start();
      new Thread("t4") {
         public void run() {
            EndSingleClassDemo endSingleClassDemo = EndSingleClassDemo.getmLazSingleClassDemo();
            System.out.println(this.getName());
            System.out.println(endSingleClassDemo);
         }
      }.start();
      new Thread("t5") {
         public void run() {
            EndSingleClassDemo endSingleClassDemo = EndSingleClassDemo.getmLazSingleClassDemo();
            System.out.println(this.getName());
            System.out.println(endSingleClassDemo);
         }
      }.start();


      long beginTime = System.currentTimeMillis();
      for (int i = 0; i < 100000; i++) {
         EndSingleClassDemo endSingleClassDemo = EndSingleClassDemo.getmLazSingleClassDemo();
      }
      long endTime = System.currentTimeMillis();

      System.out.println("用时间:" + (endTime - beginTime));
      
      /*
      打印结果如下:
      
      创建懒加载模式的对象
      t1
      t2
      t3
      top.wintp.demo.EndSingleClassDemo@4dbb3e34
      top.wintp.demo.EndSingleClassDemo@4dbb3e34
      top.wintp.demo.EndSingleClassDemo@4dbb3e34
      t4
      top.wintp.demo.EndSingleClassDemo@4dbb3e34
      t5
      top.wintp.demo.EndSingleClassDemo@4dbb3e34
      用时间:1
       */

   }
}


一个优秀的程序员,不仅要会编写程序,更要学会编写高质量的程序。 事虽难,做则成;路虽远,行则至。

原文地址:https://blog.csdn.net/pyfysf/article/details/83870637?ops_request_misc=&request_id=42e68fa23fde409eb981631ce130651a&biz_id=&utm_medium=distribute.pc_search_result.none-task-blog-2~all~koosearch~default-11-83870637-null-null.142^v88^insert_down28v1,239^v2^insert_chatgpt&utm_term=java%E4%BC%98%E5%8C%96

本文章网址:https://www.sjxi.cn/detil/7c8ba8d02044429d9243511bfb717513

最新评论

当前未登陆哦
登陆后才可评论哦

湘ICP备2021009447号