java多线程编程核心技术——第六章总结

1.0立即加载/“饿汉式”

  立即加载:实用类的时候已经将对象创建完毕,常见的实现方法就是直接new实例化。

  注:是在调用方法前,就已经实例化了(通常是在类一加载的时候就已经实例化了)。

public class Singleton {
    //立即加载方法==饿汉式
    private static Singleton singleton = new Singleton();

    private Singleton() {
    }

    public static Singleton getInstance() {
        //此代码版本为立即加载
        //此代码版本缺点:是不能有其他实例变量
        //因为getInstance()方法没有同步
        //所以可能出现非线程安全问题
        return singleton;
    }
}

2.0延迟加载/“懒汉式”

  延迟加载:在调用get()方法时实例才被创建,常见的实现办法就是在get()中进行实例化。

  注:在调用获取实例的方法时,实例才被创建。

public class Singleton {
    private static Singleton singleton;

    private Singleton(){}

    public static Singleton getInstance() {
        //延迟加载,若多个线程在此if失去执行权,最终会产生很多实例对象
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
}

  可以使用synchronized方法或者synchronized同步代码块解决多线程中的同步问题,但是效率较低。

  书中提供了双检查锁机制:

  可以使用DCL双检查锁机制实现单例:

public class Singleton {
    private volatile static Singleton singleton;

    private Singleton(){}
    //使用双检查锁机制来解决问题,既保证了不需要使用同步代码块的异步执行性,又保证了单例效果。

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

  注:关于双检索的争议还是有很多的,但是目前可以认为其实安全的。

  双检查锁的安全性问题总结(未完成)

3.0使用静态内置类实现单例模式

public class Singleton {
    //内部类形式
    private static class MyHanlder {
        private static Singleton singleton = new Singleton();
    }

    private Singleton() {}

    public static Singleton getInstance() {
        return MyHanlder.singleton;
    }
}

4.0序列化与反序列化的单例模式实现

  虽然静态内置类可以达到线程安全,但如果遇到序列化对象,使用默认的方式运行得到的还是多例。

public class Singleton implements Serializable{
    private static final long seroalVersionUID = 888L;

    //内部类形式
    private static class MyHanlder {
        private static Singleton singleton = new Singleton();
    }

    private Singleton() {}

    public static Singleton getInstance() {
        return MyHanlder.singleton;
    }

    protected Object readResolve() throws ObjectStreamException {
        return MyHanlder.singleton;
    }
}

  书写readResolve()方法就可以避免在序列化与反序列化的过程中单例失效。

  注:目前为什么这样还不理解。

5.0使用static代码块实现单例模式

  静态代码块中的代码在使用类的时候就已经执行了,所以可以应用静态代码块的这个特性来实现单例设计模式。

public class Singleton implements Serializable{
    private static Singleton singleton = null;

    private Singleton() {}

    static {
        singleton = new Singleton();
    }

    public static Singleton getInstance() {
        return singleton;
    }
}

6.0使用enum枚举数据类型实现单例模式

  枚举与静态代码块类似,在使用枚举时,构造方法会被自动调用,也可以使用其这个特性实现单例设计模式。

本文内容是书中内容兼具自己的个人看法所成。可能在个人看法上会有诸多问题(毕竟知识量有限,导致认知也有限),如果读者觉得有问题请大胆提出,我们可以相互交流、相互学习,欢迎你们的到来,心成意足,等待您的评价。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java学习之路

Hibernate学习---关联关系映射

关联关系是用到的最多的一种关系,非常重要,在内存中反映为实体关系,映射到DB中主键外键关系,实体间的关联,即对外键的维护,关联关系的发生,即对外键数据的改变。 ...

2886
来自专栏Java技术

面试中有哪些经典的数据库问题?

1、如果我们定义了主键(PRIMARY KEY),那么InnoDB会选择主键作为聚集索引、如果没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的唯...

971
来自专栏MYSQL轻松学

面试中有哪些经典的数据库问题?

1、如果我们定义了主键(PRIMARY KEY),那么InnoDB会选择主键作为聚集索引、如果没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的唯...

1350
来自专栏黑泽君的专栏

day44_Oracle学习笔记_03

先去Oracle官网去下载最新版本的sqldeveloper,下载地址:https://www.oracle.com/technetwork/developer...

872
来自专栏开发

mysql学习之优化总结(2)--索引的那些事

上一篇文章我们在研究MySQL查询过程的查询优化步骤中提到过优化索引可以优化查询优化的过程,索引到底是什么?它在查询过程中是一个怎样的角色?索引适用于什么场景?...

1725
来自专栏cs

python链接mysql数据库

PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,Python2中则使用mysqldb。

1064
来自专栏Java Edge

MySQL索引及其实现原理(基于MyISAM及InnoDB引擎)1 数据结构及算法基础2. MySQL索引实现3. 索引使用策略及优化Hash索引的特点Hash索引的限制

9078
来自专栏Java进阶架构师

「mysql优化专题」90%程序员面试都用得上的索引优化手册(5)【面试重点】

索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。更通俗的说,索引就相当于目录。当你在用新华字典...

1013
来自专栏小狼的世界

Mysql运行模式及1690错误处理

经过查询,发现这个错误的原因是两个时间字段进行减法运算时,如果有一个时间为0000-00-00时造成的,根本原因是因为这样减法的结果会超过Mysql数值字段的范...

992
来自专栏WindCoder

网易MySQL微专业学习笔记(八)-MySQL字符集

这个系列属于个人学习网易云课堂MySQL数据库工程师微专业的相关课程过程中的笔记,本篇为其“MySQL数据库对象与应用”中的MySQL数据类型相关笔记。

472

扫码关注云+社区