IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 面试官:来聊聊单例模式吧? -> 正文阅读

[Java知识库]面试官:来聊聊单例模式吧?

设计模式分为三大类:
创建型模式:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式: 适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式: 策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

单例模式定义:
单例模式确保某个类只有一个实例,并提供一个访问它的全局访问点。主要解决一个全局使用的类频繁地创建与销毁。控制实例数目,节省系统资源。

单例模式的特点:
单例类只能有一个实例。
单例类必须自己创建自己的唯一实例。
单例类必须给所有其他对象提供这一实例。
单例模式保证了全局对象的唯一性,比如系统启动读取配置文件就需要单例保证配置的一致性。

单例的四大原则:
构造私有
以静态方法或者枚举返回实例
确保实例只有一个,尤其是多线程环境
确保反序列换时不会重新构建对象

实现单例模式的方式:
(1)饿汉式(立即加载):
饿汉式单例在类加载初始化时就创建好一个静态的对象供外部使用,除非系统重启,这个对象不会改变,所以本身就是线程安全的。
Singleton 通过将构造方法限定为 private 避免了类在外部被实例化,在同一个虚拟机范围内,Singleton 的唯一实例只能通过 getInstance()方法访问。(事实上,通过 Java 反射机制是能够实例化构造方法为 private 的类的,会使 Java单例实现失效)

/**
 * @Author huang.bX
 * @Date 2021/7/21
 */
public class SingletonTest01 {
    public static void main(String[] args) {
        Hungry instance = Hungry.getInstance();
        Hungry instance1 = Hungry.getInstance();
        Hungry instance2 = Hungry.getInstance();
        System.out.println(instance.getClass());
        System.out.println(instance1.getClass());
        System.out.println(instance2.getClass());
    }
}

//饿汉式
class Hungry {
    //1构造器私有化  外部不能直接new
    private Hungry() {
    }
    //2本类的内部创建实例
    private final static Hungry hungry = new Hungry();

    //提供一个全局访问点共有的静态方法 返回实例对象
    public static Hungry getInstance(){
        return hungry;
    }
}

在这里插入图片描述
(2)懒汉式(延迟加载):
该示例虽然用延迟加载方式实现了懒汉式单例,但在多线程环境下会产生多个 Singleton 对象

/**
 * @Author huang.bX
 * @Date 2021/7/21
 */
public class SingletonTest03 implements Runnable {

    @Override
    public void run(){
        for (int i=1;i<1000;i++){
            LazyMan lazyMan=LazyMan.getInstance();
            System.out.println(lazyMan.hashCode());
        }
    }
    public static void main(String[] args) {
        /*
         *   LazyMan instance1 = LazyMan.getInstance();
         *   LazyMan instance2 = LazyMan.getInstance();
         *  System.out.println(instance1.hashCode()==instance2.hashCode());
        */
       new Thread(new SingletonTest03()).start();
       new Thread(new SingletonTest03()).start();
       new Thread(new SingletonTest03()).start();


    }
}

class LazyMan{
    private LazyMan(){

    }
    private static LazyMan lazyMan;

    //public static LazyMan getInstance()线程不安全
    public static synchronized LazyMan getInstance(){
        if (lazyMan==null){
           lazyMan = new LazyMan();
        }
        return lazyMan;
    }
}

在这里插入图片描述
(3)双重检查锁(提高同步锁的效率):
使用双重检查锁进一步做了优化,可以避免整个方法被锁,只对需要锁的代码部分加锁,可以提高执行效率。

/**
 * @Author huang.bX
 * @Date 2021/7/21
 */
public class SingletonTest05 {
    public static void main(String[] args) {
        DoubleLock instance1 = DoubleLock.getInstance();
        DoubleLock instance2 = DoubleLock.getInstance();
        System.out.println(instance1.hashCode()==instance2.hashCode());
    }
}

class DoubleLock{

    private static volatile DoubleLock doubleLock;
    private DoubleLock(){}

    public static DoubleLock getInstance(){
        if (doubleLock==null){
            synchronized (DoubleLock.class){
                if (doubleLock==null){
                    doubleLock = new DoubleLock();
                }
            }
        }
        return doubleLock;
    }
}

在这里插入图片描述
(4) 静态内部类:
这种方式引入了一个内部静态类(static class),静态内部类只有在调用时才会加载,它保证了 Singleton 实例的延迟初始化,又保证了实例的唯一性。它把 singleton 的实例化操作放到一个静态内部类中,在第一次调用 getInstance() 方法时,JVM 才会去加载 InnerObject 类,同时初始hsingleton 实例,所以能让 getInstance() 方法线程安全。特点是:即能延迟加载,也能保证线程安全。静态内部类虽然保证了单例在多线程并发下的线程安全性,但是在遇到序列化对象时,默认的方式运行得到的结果就是多例的。

/**
 * @Author huang.bX
 * @Date 2021/7/21
 */
public class SingletonTest06 {
    public static void main(String[] args) {
        StaticInClass instance1 = StaticInClass.getInstance();
        StaticInClass instance2= StaticInClass.getInstance();
        System.out.println(instance1.hashCode()==instance2.hashCode());
    }
}

class StaticInClass{

    private static volatile StaticInClass staticInClass;
    //构造器私有化
    private StaticInClass(){}

    //定义一个静态内部类,该类中有一个静态属性
    private static class Inner{
        private static final StaticInClass INSTANCE = new StaticInClass();
        
    }
    public static synchronized StaticInClass getInstance(){
        return Inner.INSTANCE;
    }

}

在这里插入图片描述

(5)枚举实现(防止反射攻击):
事实上,通过 Java 反射机制是能够实例化构造方法为 private 的类的。这也就是我们现在需要引入的枚举单例模式。

/**
 * @Author huang.bX
 * @Date 2021/7/21
 */
public class SingletonTest07 {
    public static void main(String[] args) {
        Singleton instance1 = Singleton.INSTANCE;
        Singleton instance2 = Singleton.INSTANCE;
        System.out.println(instance1.hashCode());
        System.out.println(instance2.hashCode());
        System.out.println(instance2.hashCode()==instance1.hashCode());
        System.out.println(instance1.getClass());
        System.out.println(instance2.getClass());
        System.out.println(instance1.getDeclaringClass());
    }
}

enum Singleton{
    INSTANCE;//属性
    public void say(){
        System.out.println("ok!");
    }
}

在这里插入图片描述

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-01-14 01:50:01  更:2022-01-14 01:51:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:43:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码