单例模式之饿汉,懒汉

一、饿汉模式

当类被加载时,静态变量instance就会被初始化,此时类的私有构造函数会被调用,单例类的唯一实例将被创建,不会出现创造多个单例对象的情况,可确保单例对象的唯一性,在单线程和多线程的情况下都可以保证正确性。

1)单线程

public class 单例模式之饿汉 {
    //一开始就初始化
    private static 单例模式之饿汉 instace = new 单例模式之饿汉();
    private 单例模式之饿汉(){}
    public static 单例模式之饿汉 getInstace() {
        return instace;
    }

    public static void main(String[] args){
        单例模式之饿汉 ins1 = 单例模式之饿汉.getInstace();
        单例模式之饿汉 ins2 = 单例模式之饿汉.getInstace();
        单例模式之饿汉 ins3 = 单例模式之饿汉.getInstace();

        System.out.println(ins1 == ins2);
        System.out.println(ins2 == ins3);
    }
}

结果:
在这里插入图片描述
2)多线程

public class 单例模式之饿汉 {
    //一开始就初始化
    private static 单例模式之饿汉 instace = new 单例模式之饿汉();
    private 单例模式之饿汉(){}
    public static 单例模式之饿汉 getInstace() {
        return instace;
    }

    static class MyThread extends Thread {
        @Override
        public void run() {
            单例模式之饿汉 ins1 = 单例模式之饿汉.getInstace();
            System.out.println(ins1);
        }
    }
    public static void main(String[] args){
        MyThread[] threads = new MyThread[20];
        for(int i = 0; i < 10; i++) {
            threads[i] = new MyThread();

        }
        for(int i = 0; i < 10; i++) {
            threads[i].start();
        }
    }
}

结果:
在这里插入图片描述

二、懒汉模式

1)单线程

public class 单例模式之懒汉模式 {

    private static 单例模式之懒汉模式 instance = null;

    private 单例模式之懒汉模式() { }

    public static 单例模式之懒汉模式 getInstance() {
        if(instance == null) {
            instance = new 单例模式之懒汉模式();
        }
        return instance;
    }

    public static void main(String[] args) {
        单例模式之懒汉模式 ins1 = 单例模式之懒汉模式.getInstance();
        单例模式之懒汉模式 ins2 = 单例模式之懒汉模式.getInstance();
        单例模式之懒汉模式 ins3 = 单例模式之懒汉模式.getInstance();

        System.out.println(ins1 == ins2);
        System.out.println(ins2 == ins3);
    }
}

结果:
在这里插入图片描述
2)多线程

    private volatile static 单例模式之懒汉模式 instance = null;

    private 单例模式之懒汉模式() { }
    public static 单例模式之懒汉模式 getInstance() {
        //第一次判断
        if(instance == null) {
            //内部枷锁
            synchronized (单例模式之懒汉模式.class) {
                //二次判断
                if(instance == null) {
                    //会发生重排序问题
                    instance = new 单例模式之懒汉模式();
                }
            }
        }
        return instance;
    }

    static class MyThread extends Thread {

        @Override
        public void run() {
            单例模式之懒汉模式 ins1 = 单例模式之懒汉模式.getInstance();
        }
    }

    public static void main(String[] args) {
        MyThread[] threads = new MyThread[10];
        for(int i = 0; i < 10; i++) {
            threads[i] = new MyThread();
        }
        for(int i = 0; i < 10; i++) {
            threads[i].start();
        }
    }
}

注意:

  • 加synchronized 可以防止重排序问题,内部枷锁可以提升效率
  • 之所以进行二次判断是因为抢锁成功后后条件可能发生了变化,这样可以确保唯一实例
  • instance = new 单例模式之懒汉模式();可能发生重排序问题,所以在创建静态变量instance时,在它前面加上volatile
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值