首页 > 技术文章 > 学习设计模式(单例模式)

xuerong 2018-04-24 15:14 原文

package com.xue.baozi;

/**
 * @author baozi
 *     <p>模拟创建对象的时候销毁内存资源
 *     <p>单例:就是在程序运行中,保证内存中只存在一个对象的副本
 *     实现单例的步骤:
 *     1、只能提供一个默认构造器的访问修饰符改为private(将类中的空的构造器私有化)
 *     2、在类中提供一个静态的私有的与当前类同类型的属性
 *     3、在类中提供一个创建当前类实例静态的方法
 *
 *     使用中:
 *        1、懒汉式:(推荐使用)
 *         要使用才去创建,不会浪费资源
 *        2、饿汉式:
 *          1、线程安全,但是耗费内存(如果没有用他的话,就浪费资源了)
 *          2、一进来就已经创建好了
 */public class MyConnection {
  //  public MyConnection() throws InterruptedException {
  //    Thread.sleep(1000);
  //    for (int i = 0; i < 10000; i++) {}
  //  }

  public void getConn() {
    System.out.println("获取链接对象");
  }

  /** ****************************修改为单例*************************
   * 1、只能提供一个默认构造器的访问修饰符改为private
   *
   */
  private MyConnection() {
    try {
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    for (int i = 0; i < 10000; i++) {}
    }
  /** 2、在类中提供一个静态的私有的与当前类同类型的属性 */
  private static MyConnection conn = null;
  // 饿汉式 :线程安全,但是耗费内存(如果没有用他的话,就浪费资源了)
//  private static MyConnection conn =  new MyConnection();

  /** 3、在类中提供一个创建当前类实例静态的方法 */
//  public static MyConnection newInstance() {
//    // 懒汉式单例 线程不安全
//    try {
//      if(conn == null){
//        conn = new MyConnection();
//      }
//    } catch (Exception e) {
//      e.printStackTrace();
//    }
//    return conn;
//  }

  /**
   * 由于单例存在线程安全问题所以我们得加同步锁 懒汉式
   */
  public static MyConnection newInstance() {
    // 懒汉式单例
      if(conn == null){
        // synchronized 保证在同一个时间点只能有一个线程在同一个时间片中执行
        //为啥2次判断呢(主要提升性能),假如A线程、B线程 进到synchronized这里排队,A先进去了,new 了,B进去这样就不需要new 了
        //假如没有加个非空判断,那么B线程也会重新new
        synchronized (MyConnection.class){
          if(conn == null){
            conn = new MyConnection();
          }
        }
      }
    return conn;
  }

  public static void main(String[] args) {
    // 怎么调用类中的静态方法(类.静态方法名称)
    try {
      System.out.println(MyConnection.newInstance());
      System.out.println(MyConnection.newInstance());
      System.out.println(MyConnection.newInstance());
      System.out.println(MyConnection.newInstance());
      System.out.println(MyConnection.newInstance());
      System.out.println(MyConnection.newInstance());
      /**
       * 都是同一个地址
       * com.xue.baozi.MyConnection@1540e19d
         com.xue.baozi.MyConnection@1540e19d
         com.xue.baozi.MyConnection@1540e19d
         com.xue.baozi.MyConnection@1540e19d
         com.xue.baozi.MyConnection@1540e19d
         com.xue.baozi.MyConnection@1540e19d
       */
    } catch (Exception e) {
      e.printStackTrace();
    }

  }
}

 

package com.xue.baozi;

import org.junit.Test;

/**
 * @author baozi
 * @title
 * @date 2018/4/24 14:27
 * @description
 */
public class ConnnectionTest {
//
//  @Test
//  public void connnectionTest() {
//    try {
//      //获取执行前时间毫秒值
//      long startTimeMills = System.currentTimeMillis();
//      System.out.println(startTimeMills);
////      MyConnection myConnection = new MyConnection();
//      // MyConnection myConnection  = new MyConnection(); 执行时间为:1002
//      for (int i = 0; i < 20; i++) {
////          MyConnection myConnection = new MyConnection();
//        // MyConnection myConnection  = new MyConnection(); 执行时间为:20011
////        myConnection.getConn();
//      }
//      long endTimeMills = System.currentTimeMillis();
//      System.out.println(endTimeMills);
//      System.out.println("执行时间为:" + (endTimeMills - startTimeMills));
//    } catch (Exception e) {
//      e.printStackTrace();
//    }
//  }

    @Test
    public void connnectionTest() {
        try {
            //获取执行前时间毫秒值
            long startTimeMills = System.currentTimeMillis();
            System.out.println(startTimeMills);
            for (int i = 0; i < 20; i++) {
                // 执行时间为:1002 相当于上面方法在for外面的时间 提高了很多
              MyConnection myConnection = MyConnection.newInstance();
              myConnection.getConn();
            }
            long endTimeMills = System.currentTimeMillis();
            System.out.println(endTimeMills);
            System.out.println("执行时间为:" + (endTimeMills - startTimeMills));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

推荐阅读