zoukankan      html  css  js  c++  java
  • java单例模式

    单例模式:运行期间有且仅有一个实例

    一. 关键点:

    1.一个类只有一个实例------最基本的-----(只提供私有构造器)

    2.该类必须自行创建这个实例-----(定义了静态的该类的私有对象)

    3.该类必须自行向整个系统提供这个实例---(提供一个静态的公有方法,返回创建或者获取本身的静    态私有对象)

    二.基本单例模式

    1.懒汉模式

    懒汉模式:在类加载的时候,不创建实例,运行调用的时候创建(以时间换空间

       优缺点:类加载快,在运行时获取速度慢;线程不安全;

    解决懒汉模式线程安全方法:(1)方法体加同步(2)双重校验锁

    懒汉模式特性:lazy  Loading(延迟加载)    

    2.饿汉模式

    饿汉模式:在类加载的时候就会完成初始化。(以空间换时间

    优缺点:类加载慢,但在运行时获取对象速度快;线程安全

     三.代码展示  

    懒汉模式代码:

    import java.io.IOException;

    import java.io.InputStream;

    import java.util.Properties;

    /**

     * 读取数据库配置文件的工具类--单例模式

     * */

    public class ConfigManager {

    // 01定义静态私有本类对象

    private static ConfigManager configManager;

    private static Properties properties;

    // 02私有化本类构造方法--读取配置文件

    private ConfigManager() {

    // 定义要读取的配置文件

    String configFile = "database.properties";

    properties = new Properties();

    // 以输入流的形式获取配置文件

    /**

     * ConfigManager.class.getClassLoader():获取本类根目录

     * getResourceAsStream(configFile):以流的形式获取配置文件

     * */

    InputStream is = ConfigManager.class.getClassLoader()

    .getResourceAsStream(configFile);

    try {

    // 读取配置文件(把流放入properties对象)

    properties.load(is);

    } catch (IOException e) {

    e.printStackTrace();

    } finally {

    try {

    // 关闭流

    is.close();

    } catch (IOException e) {

    e.printStackTrace();

    }

    }

    }

    //03 提供全局访问接口

    /**

     * 懒汉模式:线程不安全,在多线程并发情况下,

     * 可能会创建多个ConfigManager实例

     *

     *

     * 001简单懒汉模式--适合单线程安全

     * public static ConfigManager getInstance() {

    if (configManager == null) {

    configManager = new ConfigManager();

    }

    return configManager;

    }

     * 解决线程安全问题:

     //002.方法体加同步,每一个时间点只允许一个线程通过该方法

    public static  synchronized ConfigManager getInstance() {

    if (configManager == null) {

    configManager = new ConfigManager();

    }

    return configManager;

    }

    // 04获得properties对象的值

    public String getString (String key) {

    return properties.getProperty(key);

    }

     

           饿汉模式代码

     1 import java.io.IOException;
     2 import java.io.InputStream;
     3 import java.util.Properties;
     4 
     5 /**
     6  * 读取数据库配置文件的工具类--单例模式
     7  * */
     8 public class ConfigManager {
     9     // 01定义静态私有本类对象
    10        private static ConfigManager configManager=new ConfigManager();//初始化实例
              private static Properties properties;
    15     // 02私有化本类构造方法--读取配置文件
    16     private ConfigManager() {  
    17         // 定义要读取的配置文件
    18         String configFile = "database.properties";
    19         properties = new Properties();
    20         // 以输入流的形式获取配置文件
    21         /**
    22          * ConfigManager.class.getClassLoader():获取本类根目录
    23          * getResourceAsStream(configFile):以流的形式获取配置文件
    24          * */
    25         InputStream is = ConfigManager.class.getClassLoader()
    26                 .getResourceAsStream(configFile);
    27         try {
    28             // 读取配置文件(把流放入properties对象)
    29             properties.load(is);
    30         } catch (IOException e) {
    31             e.printStackTrace();
    32         } finally {
    33             try {
    34                 // 关闭流
    35                 is.close();
    36             } catch (IOException e) {
    37                 e.printStackTrace();
    38             }
    39         }
    40     }
    41     //03 提供全局访问接口
    42     
    69 /*饿汉模式
    70  * 线程安全:在加载类时创建实例,因为实例是static,
    71  *所以只加载一次
    72  * */
    73     
    74     public static   ConfigManager getInstance(){
    75         return  configManager;
    76     }
    77 
    78 
    79     // 04获得properties对象的值
    80     public String getString (String key) {
    81         return properties.getProperty(key);
    82     }
    83 }

     饿汉模式变种:静态代码块

     public class SingleTon {
     // 饿汉模式变种:静态代码块
          private static SingleTon singleTon = null;
           static {
     //类加载是执行静态代码块,只执行一次
           singleTon = new SingleTon();
          }
    private SingleTon() { }
       public static SingleTon getInstance() {
             return singleTon;
    }
       }
    View Code

    懒汉模式线程安全之双重校验锁

    private static SingleTon singleTon;
     
    private SingleTon() {
    }
     
    public static SingleTon getInstance() {
              if (singleTon == null) {//第一重校验(第一批并发线程以后的线程不会通过这里,因为已经实例化)
                      synchronized (SingleTon.class) {//锁,类同步安全(只允许一批并发线程中的一个线程通过)
                             if (singleTon == null) {//第二重校验(非空判断,实例为空通过,不为空止步)
                                          singleTon = new SingleTon();//校验全部通过,创建实例
                          }
                  }
           }
                     return singleTon;
             }
    }
    View Code

     测试模拟多线程并发与双重锁

    package cn.bdqn.util;
    /**
     * 线程类
     * 模拟多线程并发
     * */
    public class ThreadDemo extends Thread {
    private String threadNo;
    public ThreadDemo() {
    }
    public ThreadDemo(String threadNo) {
    this.threadNo = threadNo;
    }
    public String getThreadNo() {
    return threadNo;
    }
    public void setThreadNo(String threadNo) {
    this.threadNo = threadNo;
    }
     
    @Override
    public void run() {
           super.run();
    //调用单利模式方法,模拟测试双重锁
           System.out.println(threadNo);
           SingleTon.getInstance(threadNo);
         }
    }
    View Code
    package cn.bdqn.util;
    /*
     * 测试类,测试线程双重锁
     *
     * */
    public class ThreadTest {
     
    public static void main(String[] args) {
    for (int i = 0; i < 7; i++) {// 相当于主线程,获取资源之后,瞬间生成n个子线程,相当于并发
                  new ThreadDemo("线程" + i).start();// 创建子线程,并开启
                   if (i == 3) {
                      try {
                             Thread.sleep(1000);//模拟多批线程先后并发
                             System.out.println("sleep*********");
                           } catch (InterruptedException e) {
                                    e.printStackTrace();
                    }
                }
           }
    View Code

    执行结果:

    静态内部类:解决饿汉模式实现lazy loading(延迟加载)

    //创建静态变量
    private static SingleTon singleTon;
    //私有构造
    private SingleTon(){}
    //静态内部类
    private static class SingleTonHelp{
     //创建静态常量,完成实例化
    private static final SingleTon INSTANCE=new SingleTon();
    }
       //提供全局访问的接口
    public static SingleTon  getInstance(){
    return SingleTonHelp.INSTANCE;
    }
      //测试方法
    public static void test(){
    System.out.println("test==============="+singleTon.toString());
    }
    View Code
    package cn.bdqn.util;
    /**
     * 测试静态内部类
     *
     * */
    public class Test02 {
    public static void main(String[] args) {
    System.out.println("SingleTon.getInstance()======="+SingleTon.getInstance().toString());
    //此时test()报空指针异常,因为没有调用静态类方法,没有加载实例,达到延迟加载效果(即在需要时加载创建实例,不会加载类时加载实例)
        SingleTon.test();
    }
    }
    View Code

    什么时候使用单利模式:在比较耗系统性能的时候,比如i/o操作,读取配置文件

    懒汉模式特性:lazy  Loading(延迟加载)

    懒汉模式:以时间换空间

    饿汉模式:以空间换时间(标准饿汉模式为常用模式,不存在线程安全问题)

     

  • 相关阅读:
    2、容器初探
    3、二叉树:先序,中序,后序循环遍历详解
    Hebbian Learning Rule
    论文笔记 Weakly-Supervised Spatial Context Networks
    在Caffe添加Python layer详细步骤
    论文笔记 Learning to Compare Image Patches via Convolutional Neural Networks
    Deconvolution 反卷积理解
    论文笔记 Feature Pyramid Networks for Object Detection
    Caffe2 初识
    论文笔记 Densely Connected Convolutional Networks
  • 原文地址:https://www.cnblogs.com/liu-chao-feng/p/5971592.html
Copyright © 2011-2022 走看看