安卓学习模式系列---单例模式小结

本文深入解析单例模式的七种实现方式,包括恶汉式、懒汉式(四种变体)、静态内部类及内部容器,探讨每种方式的优缺点,并通过示例代码展示其在多线程环境下的应用与问题解决。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单例模式

定义:一种最最常见的一种模式,保证整个程序中只有一个实例
常见写法
1恶汉式

/**
 * @author ${Li}
 * 版本:1.0
 * 创建日期:2020/4/8 21
 * 描述:1.单例 模式 恶汉式
 * 随着类的加载就已经 new 了对象
 */
public class SingleDemo {
    public static SingleDemo mInstance = new SingleDemo();

    private SingleDemo(){

    }

    public static SingleDemo getmInstance() {
        return mInstance;
    }
}

2懒汉式(1)

/**
 * @author ${Li}
 * 版本:1.0
 * 创建日期:2020/4/8 21
 * 描述:2.单例模式 懒汉式(1)
 *   优点: 只有使用时才加载 效率更高
 *  问题: 多并发可能会有多个实例
 */
public class SingleDemo {

    private static SingleDemo mInstance ;

    private SingleDemo(){

    }

    public static SingleDemo getmInstance() {
        if (mInstance==null){//线程a进入还没有new SingleDemo(),
        // b进入 mInstance为空 ab都创建了实例
            mInstance = new SingleDemo();
        }
        return mInstance;
    }
}

3.懒汉式(2)

/**
 * @author ${Li}
 * 版本:1.0
 * 创建日期:2020/4/8 21
 * 描述:2.单例模式 懒汉式(2) 解决 懒汉(1)的问题
 *   优点: 利用锁解决(1)线程安全问题
 *  问题:  每次调用都判断锁引起效率问题
 */
public class SingleDemo1 {

    private static SingleDemo1 mInstance ;

    private SingleDemo1(){

    }

    public static synchronized SingleDemo1 getmInstance() {
        if (mInstance==null){//线程a进入还没有new SingleDemo(),
        // b进入 mInstance为空 ab都创建了实例
            mInstance = new SingleDemo1();
        }
        return mInstance;
    }
}

4.懒汉式(3)

/**
 * @author ${Li}
 * 版本:1.0
 * 创建日期:2020/4/8 21
 * 描述:2.单例模式 懒汉式(3) 解决 懒汉(2)的问题
 *   优点:  既保证线程安全效率也较高
 *  问题:  还会可能出现多线程并发的问题,可能还是会存在多个实例
 */
public class SingleDemo2 {

    private static SingleDemo2 mInstance ;

    private SingleDemo2(){

    }


    public static SingleDemo2 getmInstance() {
        if (mInstance==null){ //判断为空进来
            synchronized (SingleDemo2.class){//加锁保证线程安全 只有1个能进入
                if (mInstance==null){//再次判断是否为空,是空创建  创建后mInstance不为空
                // 无法进入到synchronized锁里面来
                    mInstance = new SingleDemo2();
                }
            }

        }
        return mInstance;
    }
}

5懒汉式(4)

/**
 * @author ${Li}
 * 版本:1.0
 * 创建日期:2020/4/8 21
 * 描述:2.单例模式 懒汉式(4) 解决 懒汉(3)的问题 终极版
 *   优点:  既保证线程安全效率也较高 加 volatile字段
 *  问题:
 */
public class SingleDemo3 {
//    volatile字段作用
    /*   1.防止重新排序的问题
        java 正常初始化排序
        (1)开辟内存空间
         (2) 初始化对象
        (3)给变量赋值(指向内存的地址)
        java 可能出现的排序 2.3是可换的
          先赋值在初始化对象 就会出现mInstance不为null 从而没有new的情况没有初始化
    *    2.线程可见性 因为每一个线程都有各自的缓存区在改变对象时可能出现改变变量,
    *    短时间另一个线程可能是不可见的(试例)
    * */

    private static volatile SingleDemo3 mInstance ;

    private SingleDemo3(){

    }

    public static synchronized SingleDemo3 getmInstance() {
        if (mInstance==null){ //判断为空进来
            synchronized (SingleDemo3.class){//加锁保证线程安全 只有1个能进入
                if (mInstance==null){//再次判断是否为空,是空创建  创建后mInstance不为空 无法进入到synchronized锁里面来
                    mInstance = new SingleDemo3();
                }
            }

        }
        return mInstance;
    }
}

注意:
网上学习时候有很多例子都没有这个字段,在学习过程与查找资料中还是在里面加上了volatile字段,在查找资料和不断验证下我发现了这个例子

volatile实例

/**
 * @author ${Li}
 * 版本:1.0
 * 创建日期:2020/4/8 22
 * 描述:volatile 的例子 可以看出线程可见性
 */
public class VolatileDemo {

    public static void main(String[] args) {
        ThreadTestDemo ttd = new ThreadTestDemo();
        new Thread(ttd).start();
        while(true){
            if(ttd.isFlag()){
                System.out.println("------------------");
                break;
            }
        }
//        不加volatile 输出为   flag=true

//        加 volatile 输出为    ------------------
//                              flag=true

    }
}
class ThreadTestDemo implements Runnable {
//    private volatile boolean flag = false;
    private  boolean flag = false;
    @Override
    public void run() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
        }
        flag = true;
        System.out.println("flag=" + isFlag());
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

}

6.静态内部类 (常用)

/**
 * @author ${Li}
 * 版本:1.0
 * 创建日期:2020/4/8 22
 * 描述:单例模式 静态内部类 (常用)
 */
public class SingleDemo {
    private SingleDemo(){

    }
    private static class SingleDemoHolder{
        private static volatile SingleDemo mInstance= new SingleDemo();
    }

    public static SingleDemo getInstance() {
        return SingleDemoHolder.mInstance;
    }

}

7.内部容器

package com.li.demol_day4_8.demo4;

import java.security.Key;
import java.util.HashMap;
import java.util.Map;

/**
 * @author ${Li}
 * 版本:1.0
 * 创建日期:2020/4/8 22
 * 描述:单例模式内部容器
 */
public class SingleDemo {
    private static Map<String, Object> objectMap = new HashMap<>();

    static {
        objectMap.put("mDemo", new SingleDemo());
    }

    private SingleDemo() {

    }

    public static Object getObjectMap(String key) {
        return objectMap.get(key);
    }
}


说明:

在学习过程中在网上找了很多资料看了很多大神的笔记,所以的技术基础都是类似的,这里就细说看了那个大神的博客了,反正看了很多的自己也是在学习中总结,可能在代码中会有问题 请发现问题多进行指正,交流学习,写博客的目的是碎片化记忆,能随时查找自己的笔记。接下来可能在此会写一系列的学习笔记,请多指教

github地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值