Java开发中的23种设计模式——单例模式

前言

设计模式(Design Pattern)
是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。

开发中的最高境界便是没有设计模式,因为你所编写的每一行代码都自发的趋于最优解。

单例模式

是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。

  1. 饿汉式
    之所以称为饿汉式,是因为对象随着类的加载已经创建的,凸显的比较“饥饿”,仅此而已。
    优点:避免了线程安全问题,它是绝对线程安全的。
    缺点:很明显,可能容易造成内存浪费,因为对象在类加载时就已经被创建,这是如果暂时用不到,就会造成资源浪费。
//一般方式
class Singleton{
	//创建对象(new一次)
    private final static Singleton instance = new Singleton();
    //私有化构造器
    private Singleton(){}
    //静态返回
    public static Singleton getInstance(){
        return instance;
    }
}
//静态代码块方式
class Singleton{
	//定义但未初始化
    private final static Singleton instance;
    //私有化构造器
    private Singleton(){}
    //静态代码块赋值
    static {
        instance = new Singleton();
    }
    public static Singleton getInstance(){
        return instance;
    }
}
  1. 懒汉式
    见名知意,相比饿汉式,它的特点便是,使用时才开始创建,所以比较“懒”。
    优点:与饿汉式形成对比,节省内存。
    缺点:一般线程不安全,改进扩展后可以。
//懒汉式(线程不安全)
class Singleton{
    private static Singleton instance;
    //私有化构造器
    private Singleton(){}
    //多个线程同时调用的话就会new出多个对象
    public static Singleton getInstance(){
    	//多个线程同时进入会判断对象为null
        if(instance==null){
        	//从而创建对个对象 不再是单例
            instance = new Singleton();
        }
        return instance;
    }
}

改进:加入同步锁之后,线程安全问题解决,但效率极低

//懒汉式(线程安全 效率低)
class Singleton{
    private static Singleton instance;
    //私有化构造器
    private Singleton(){}
    //同步方法 每次只能有一个线程进入
    public static synchronized Singleton getInstance(){
    	//每个线程依次进入进行判断是否为null,效率极低
        if(instance==null){
            instance = new Singleton();
        }
        return instance;
    }
}
//懒汉式(线程安全 效率低)
class Singleton{
    private static Singleton instance;
    //私有化构造器
    private Singleton(){}
    
    public static Singleton getInstance(){
    	//同步代码块方式(左右与上述一致 写法不同) 每次只能有一个线程进入
    	//每个线程依次进入进行判断是否为null,效率极低
        synchronized (Singleton.class){
            if(instance==null){
                instance = new Singleton();
            }
        }
        return instance;
    }
}

上述问题:线程安全问题是解决了,但是效率十分低,因为只需要第一个线程进入之后判断是否为null,然后new一个对象,后面的线程进入只需要return返回就行了,如果继续等待同步锁,一次进入,就会造成效率问题。
继续改进:进行双重检验,在第二种的基础上再嵌套一层判空,这样的话除了前几个线程(跟随第一个线程同时进入)需要进入等待之外,其他线程在对象创建完成之后,只在最外层判空就行了(这一步骤是所有之后线程可以同时进行的,故效率高)。

//懒汉式(线程安全 推荐)
class Singleton{
    private static volatile Singleton instance;
    //私有化构造器
    private Singleton(){}
    public static Singleton getInstance(){
        //同步代码块(双重检查)
        if (instance==null){
        	//这一层只有前几个线程同时进入
        	//待第一个线程创建对象完成之后,之后的所有线程不会再进入等待
            synchronized (Singleton.class){
                if(instance==null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
  1. 静态内部类

//静态内部类(线程安全 省内存)
利用静态内部类的特殊机制(外层类加载时,内部类即便是静态的,也不会随之加载,这样一来,就不会造成内存浪费,只在调用时创建完成,并且线程是绝对安全的)。

class Singleton{
    //私有化构造器
    private Singleton(){}
    //静态内部类
    private static class SingletonInstance{
        private static final Singleton instance = new Singleton();
    }
    //return方法
    public static Singleton getInstance(){
        return SingletonInstance.instance;
    }
}
  1. 枚举
    简单粗暴枚举法
    绝对单例,绝对线程安全,绝对不内存浪费
//枚举
enum Singleton{
    instance;//属性
}

以上便是我学习过程中总结的一些思想和笔记,大家可以在学习过程中多交流,共同进步。——一个从入门到入土的程序小白。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值