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

      概述

      单例模式是Java中常见的设计模式,常见的单例模式有三种实现方式:懒汉式,饿汉式,改进型的懒汉式。

      单例模式的特点是:

       (1)单例模式只能有一个实例,并且不能被外部实例化

       (2)单例模式必须自己创建自己的唯一实例

       (3)单例模式必须对其他对象共享自己的唯一实例

      懒汉式实现

    package com.jyk.singleton.test;
    
    public class HungrySingle {
        
        private static HungrySingle hungrySingle = null;
    
        private HungrySingle() {}
        
        public static HungrySingle getInstance(){
            if(hungrySingle == null){
                return new HungrySingle();
            }
            return hungrySingle;
        }
    }

      饿汉式实现

    package com.jyk.singleton.test;
    
    public class LazySingle {
        
        private LazySingle(){}
    
        private static LazySingle lazySingle = new LazySingle();
        
        public static LazySingle getInstance(){
            return lazySingle;
        }
    }

      懒汉式和饿汉式区别

      懒汉式和饿汉式模式都是单例模式的实现。

      饿汉式是线程安全的,因为在类初始化的时候便已经创建了对象,此后getInstance时,只需将创建好的对象返回即可,但该实现会导致类创建时便创建对象,而且是static的修饰的,所以会一直保存在内存中。

      而懒汉式不是线程安全的,假设两个线程A,B同时进入了getInstance,A走完if判断出来此时对象还创建,此时B进到判断条件后对象仍为null,所以可能会导致两个实例的创建。但懒汉式相比饿汉式的优点是,对象在使用时才创建,不会在类创建时便跟着产生,从而减少了内存堆的压力。

      改进型懒汉式:通过同步操作加上双重判定保证线程安全

      (1)在getInstance方法上添加同步操作

    package com.jyk.singleton.test;
    
    public class ReformSingle {
    
        private ReformSingle(){}
        
        private static ReformSingle reformSingle = null;
        
        public static synchronized ReformSingle getInstance(){
            if(reformSingle == null){
                return new ReformSingle();
            }
            return reformSingle;
        }
    }

      (2)双重检查锁定

    package com.jyk.singleton.test;
    
    public class ReformSingle {
    
        private ReformSingle(){}
        
        private static ReformSingle reformSingle = null;
        
        public static ReformSingle getInstance(){
            if(reformSingle == null){
                synchronized (ReformSingle.class) {
                    if(reformSingle == null){
                        return new ReformSingle();
                    }
                }
            }
            return reformSingle;
        }
    }

      懒汉式再优化:volatile关键字

    package com.jyk.singleton.test;
    
    public class ReformSingle {
    
        private ReformSingle(){}
        
        private static volatile ReformSingle reformSingle = null;
        
        public static ReformSingle getInstance(){
            if(reformSingle == null){
                synchronized (ReformSingle.class) {
                    if(reformSingle == null){
                        return new ReformSingle();
                    }
                }
            }
            return reformSingle;
        }
    }

      为什么要做如此优化呢?如上未添加 volatile关键字的双重检验单例模式的实现,是存在风险的,分析如下:

      (1)线程A,B同时进入了getInstance方法,此时A判断对象为null,进入同步块

      (2)当A部分实例化对象时,B判断不为空,直接返回一个部分实例化的对象

      添加volatile后,当A实例化对象时,B线程会等到该对象对应的主存地址更新后,再读取最新的值。

      备注:volatile关键字原理详见博客中Java常见面试题版块。

      补充:什么是线程安全

      如果你的程序是一个进程中运行的,而该进程中跑着多个线程,并且可能同时操作该部分相同的程序,若每次运行的结果和单线程执行的结果相同,并且变量值和预期的结果也是相同的,那么称之为线程安全。

      

     

      

      

  • 相关阅读:
    bx值
    玲珑杯1147
    Castle
    美团 CodeM 复赛」城市网络
    上海五校赛 密码破解
    上海五校赛 零件组装
    opencv色彩空间
    opencv对图片每个像素操作
    opencv图像的读取和保存以及调用摄像头。
    numpy的logspace产生等比数列
  • 原文地址:https://www.cnblogs.com/jiyukai/p/6697143.html
Copyright © 2011-2022 走看看