设计模式-单例模式Singleton Pattern

目录

一.单例模式的概念

二.单例模式介绍

三.代码实例

1.饿汉式单例和懒汉式单例

1.1饿汉式单例:

1.2懒汉式单例:

2.如何使懒汉式单例实现线程安全

2.1 synchronized方法

2.2 synchronized块

2.3 双检锁/双重校验锁(DCL,即 double-checked locking)

2.4 登记式/静态内部类的方法

2.5 ThreadLocal方法

3.枚举的方法实现单例模式(666)

四.利用hashcode验证线程安全


一.单例模式的概念

  • 单例模式(Singleton Pattern)属于创建型模式
  • 单例模式涉及一个单一的类,该类只负责创建自己的对象,并且保证只有一个对象被创建,该类提供一种访问其唯一的对象的方式;
  • 单例模式必须自己创建自己的唯一实例;

二.单例模式介绍

  • 解决问题:一个全局使用的类频繁地创建与销毁;
  • 使用时机:需要为系统提供一个唯一的实例:有状态的工具类对象(java的calendar);频繁访问数据库或者文件的对象;
  • 关键代码:构造函数私有(所以单例类不可被继承);getinstance()方法为static静态方法,要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入造成 instance 被多次实例化;
  • 实例:1.多台打印机,但只有一个输出池;2.Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行;
  • 三要素:
    • 1.私有的构造方法;
    • 2.以自己实例为返回值的静态的公有方法。
    • 3.指向自己实例的私有静态引用;

三.代码实例

1.饿汉式单例和懒汉式单例

  • 饿汉式单例:立即加载,在类加载初始化时就主动创建实例
  • 懒汉式单例:延时加载(Lazy Loading),在类加载是只是声明实例,并不创建;在真正使用时通过getInstance方法创建实例。

        注:两种经典单例方法都是实例化一个对象并交给自己的引用,只是创建时机不同。

1.1饿汉式单例:

// 饿汉式单例
public class Singleton1 {
    // 私有的构造方法
    private Singleton1(){}
    // 指向自己实例的私有静态引用,主动创建(饿汉式)
    private static Singleton1 singleton1 = new Singleton1();
    // 以自己实例为返回值的静态公有方法,静态工厂方法
    public static Singleton1 getSingleton1() {
        return singleton1;
    }
}

1.2懒汉式单例:

//懒汉式单例
public class Singleton2 {
    // 私有的构造方法
    private Singleton2(){}
    // 指向自己实例的私有静态引用,不主动创建实例
    private static Singleton2 singleton2 = null;
    // 以自己实例为返回值的静态公有方法,静态工厂方法
    public static Singleton2 getSingleton2() {
        // 被动创建,在真正需要时才创建实例
        if(singleton2 == null) {
           singleton2 =  new Singleton2();
        }
        return singleton2;
    }
}

访问懒汉式单例方式(其余类型访问方式类似):

Singleton2 singleton2 = Singleton2.getSingleton2();

        对比饿汉式和懒汉式,不难发现:在多线程环境下,饿汉式是天生线程安全的,因为饿汉式单例在类被加载时,就应经实例化了一个对象并交给自己的引用 ,因为类在整个生命周期只会加载一次,所以单例类只会创建一个实例,线程每次也只会访问这一个实例,所以饿汉式单例是线程安全的。但是饿汉式没有达到Lazy Loading的效果,会造成资源浪费。

        懒汉式在多线程情况下并不可用,因为它不是线程安全的:如果有多个线程想实例singleton,当线程1通过了if(singleton == null),但还未执行singleton =  new Singleton(),而此时,线程2进入了if(singleton == null),由于此时singleton的状态还是null,所以线程2也通过了判断,此时两个线程就会实例化两个Singleton对象,产生了线程安全问题。

2.如何使懒汉式单例实现线程安全

2.1 synchronized方法

//同步延迟加载 — synchronized方法
public class Singleton3 {
    private static Singleton3 singleton3 = null;
    private Singleton3(){}
    // synchronized关键字,临界资源的同步互斥访问
    public static synchronized Singleton3 getSingleton3() {
        if(singleton3 == null) {
            singleton3 = new Singleton3();
        }
        return singleton3;
    }
}

2.2 synchronized块

使用synchronized线程安全的使用方式:

//使用synchronized块实现懒汉式单例;
//安全的方式

public class Singleton4 {
    private static Singleton4 singleton4 = null;
    private Singleton4(){}

    public static Singleton4 getSingleton4() {
        // synchronized块,临界资源的同步互斥访问
        synchronized (Singleton4.class) {
            if(singleton4 == null) {
                singleton4 = new Singleton4();
            }
        }
        return singleton4;
    }
}

 使用sunnchronized线程不安全的使用方式:

// 使用synchronized块实现懒汉式单例;
// 不安全的方式
public class Singleton6 {
    private static Singleton6 singleton6 = null;
    private Singleton6(){}

    public static Singleton6 getSingleton6() {
        //线程不安全,原因类似Singleton3
        if(singleton6 == null) {
            synchronized (Singleton6.class)
            {
                singleton6 = new Singleton6();
            }
        }
        return singleton6;
    }
}

2.3 双检锁/双重校验锁(DCL,即 double-checked locking)

// 双检锁/双重校验锁(DCL,即 double-checked locking)
public class Singleton5 {
    private volatile static Singleton5 singleton5 = null;
    private Singleton5(){}
    public static Singleton5 getSingleton5() {
        // DCL
        if(singleton5 == null) {
            synchronized (Singleton5.class) {
                //只需要在第一次创建实例时才同步,提高了效率
                if(singleton5 == null) {
                    singleton5 = new Singleton5();
                }
            }
        }
        return singleton5;
    }
}

2.4 登记式/静态内部类的方法

//登记式/静态内部类的方法
public class Singleton7 {
    private Singleton7(){}
    //私有内部类,按需加载,实现延迟加载
    private static class SingletonHolder {
        private static Singleton7 singleton7 = new Singleton7();
    }
    public static Singleton7 getSingleton7() {
         return SingletonHolder.singleton7;
    }
}

2.5 ThreadLocal方法

3.枚举的方法实现单例模式(666)

//枚举(666)
public enum Singleton8 {
    INSTANCE;
    public void whateverMethod() {

    }
}

四.利用hashcode验证线程安全

谢谢观看,嘿嘿!

参考博客:

枚举实现单例模式 - SegmentFault 思否

Java设计模式—单例设计模式(Singleton Pattern)完全解析_dmk877的专栏-CSDN博客_单例设计模式java单例模式_czqqqqq的博客-CSDN博客_单例

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java设计模式是一组经过实践验证的面向对象设计原则和模式,可以帮助开发人员解决常见的软件设计问题。下面是常见的23种设计模式: 1. 创建型模式(Creational Patterns): - 工厂方法模式(Factory Method Pattern- 抽象工厂模式(Abstract Factory Pattern- 单例模式Singleton Pattern- 原型模式(Prototype Pattern- 建造者模式(Builder Pattern) 2. 结构型模式(Structural Patterns): - 适配器模式(Adapter Pattern- 桥接模式(Bridge Pattern- 组合模式(Composite Pattern- 装饰器模式(Decorator Pattern- 外观模式(Facade Pattern- 享元模式(Flyweight Pattern- 代理模式(Proxy Pattern) 3. 行为型模式(Behavioral Patterns): - 责任链模式(Chain of Responsibility Pattern- 命令模式(Command Pattern- 解释器模式(Interpreter Pattern- 迭代器模式(Iterator Pattern- 中介者模式(Mediator Pattern- 备忘录模式(Memento Pattern- 观察者模式(Observer Pattern- 状态模式(State Pattern- 策略模式(Strategy Pattern- 模板方法模式(Template Method Pattern- 访问者模式(Visitor Pattern) 4. 并发型模式(Concurrency Patterns): - 保护性暂停模式(Guarded Suspension Pattern- 生产者-消费者模式(Producer-Consumer Pattern- 读写锁模式(Read-Write Lock Pattern- 信号量模式(Semaphore Pattern- 线程池模式(Thread Pool Pattern) 这些设计模式可以根据问题的特点和需求来选择使用,它们提供了一些可复用的解决方案,有助于开发高质量、可维护且易于扩展的软件系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值