小白谈谈singleton那些事儿


时间总是过得飞快,每天奔波于工作与生活的天平两端的起跑线,总要二者兼顾,生怕哪一端会有倾斜。如此小白,怕有何用?


这是自己的第二篇原创文章了,其实说心里话,自从昨天写的第一篇文章,得到了一定的认可,也有大家的关注,自己内心心里真的是满满的感动。原创不易,且行且珍惜,有大家的支持,自己一定会更加用心写,回馈给大家每天愿意花的几分钟阅读自己的文章,在这里,再次表示感谢。愿我们的关注,永不散场。同时,自己内心心里隐约深处总会有这么一个声音,会对自己说:作为铁打的小白,你有什么干货,有什么吞吐量输出的呢?写文章花费的时间,还不如自己多看看书,多看看学习视频,如此小白,何必这样?


马老师前天说过,青山不改,绿水长流,让我们江湖再见!每个人都会有选择,马老师也做了他自己的选择,而我既然选择写,就会自己只要有好的想法心得,就会愿意花时间写写,跟大家交流交流。在如今互联网快速发展的时代,自己的往前一步会迈向何方?自己的往后退一步又会停留在哪里?面对着生活的些许琐事,已经够烦了,心还不安稳。既然认定了一条路,勇敢的走下去就是了,更何况有支持自己的人,如此小白,何必庸人自扰?


一颗心,心如止水,上善若水,用不凡的心征服自己!小白坚信,小白也会有春天,重回首,去时年,揽尽风雨苦亦甜!


好了,话不多说,直接来干吧,进入这次的主题singleton。其实这次的主题应该来说,还是自己临时加进来的,因为自己工作过程中,前后端分离,必然会有Token安全机制,在研究Redis的时候,看到了Redis工具类,入眼我的第一眼球,就是看到了构造函数的私有化,于是我嘴角微微一笑,有了,今天就singleton了,就它了。


说起singleton,或许有的人最具有话语权,就是在应聘工作的时候,面试题目会有手写singleton的这一道题,不管是否遇到or没遇到,自己这次好好的来谈谈一波,保证可以让大家印象深刻,下次遇到这 信手拈来!


其实说起单例,自己可以在心中默念几下,单例  单例,单例到底是啥东东呢,其实 可以就从字面上来理解,帮助自己更好的看清他,单例 单例,无非就是  单个的实例呗,实例是单个的。就称之为单例,这也是设计模式中的一种,这又让我想到了泛型,或许有的人会对泛型不感冒,其实我想说,不要怕它,泛型  泛型 ,从字面上来看,不就是 规范的类型嘛,哈哈,这样理解就不会让这些词汇在无形中给自己的压迫感,相反的,我们自己要认清他,理解他,了解他们的实质,弄懂他们为啥会出来的原因,这样子,我们才能驾驭它,变为属于自己的东西。


来吧,直接手写 singleton

手写前来聊一下,默认无参构造方法。都知道,在实例化一个类的时候,实际上是默认调用了该类的无参构造方法,

public class HelloWorld {
    public static void main(String[] args) {
        HelloWorld helloWorld = new HelloWorld();
        System.out.println(helloWorld);
    }
}

编译后的class文件,实际上是默认调用了无参构造方法

public class HelloWorld {
    public HelloWorld() {
    }
    public static void main(String[] args) {
        HelloWorld helloWorld = new HelloWorld();
        System.out.println(helloWorld);
    }
}

如果想往字节码方向看,也是ok的

 public HelloWorld();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1// Method java/lang/Object."<init>":()V
         4: return

在堆内存中 创建对象的时候 执行顺序

1 加载实例信息进入到 开辟的内存中

2 执行构造方法就是<init>方法

其实这字节码的关键是就是 aload_0 将0槽位 那就是this

然后invokespecial指定,构造函数的初始化。

  1. 手写单例

  2. 单例的几种形式

  3. 为啥设计单例

/**
 * @ 饿汉模式
 * @ 1 构造函数私有化  2 在初始化的时候就 new Singleton();
 * @ 字面意思 就是类加载的时候 就初始化对象,饿汉模式,太饿了
 *    相当于 就是吃的零食,饿汉模式会有限抢着零食吃
 */
public class Singleton {
    private static Singleton s = new Singleton();
    private Singleton(){
    }
    public static Singleton getSingletonInstance(){
        return s;
    }
}


/**
 * @ 懒汉模式
 * @ 1 构造函数私有化  2 在初始化的时候赋值为null
 * @ 2 在初始化得时候,赋值为是null
 * @ 字面意思 就是类加载的时候 而不初始化对象,懒汉模式,太懒了
 *   相当于 就是吃的零食,懒汉模式会有肚子饿了就会吃
 */
public class SingletonLazy {
    private static SingletonLazy s = null;
    private SingletonLazy(){
    }
    public static SingletonLazy getSingletonInstance(){
        if (s == null) {
            s = new SingletonLazy();
        }
        return s;
    }
}


以上,就是单例的最原始的 两种模式:饿汉式,懒汉式。

同时注意构造方法必须是要私有的,然后为啥会使用单例?最后static静态修饰

通过手写两种模式,注意的就是,构造方法是要私有的,这样就能确保单例,同时 static ,这就涉及到了 静态变量的全生命周期,以及类的加载机制(以后自己写写关于类加载的7个步骤,在详细的说说每一个的步骤要点)


走到这一步,或许就会说,单例也不过如此

  • 关键注意的地方,构造方法是私有的

  • 饿汉模式:太饿了,直接是new 了,类加载时候,就已经生成对象

  • 懒汉模式:不是很饿,饿的时候,才new

  • 单例模式创建实例对象,可以节省内存空间,节约资源

或许,根据这样的以上的理解,完全可以手写出来单例,同时会自我感觉良好,感觉棒棒哒!

但是呢?要切记一点,Java天生是多线程的,以上两种模式,手写的单例模式代码,是否满足要求呢,这就是要考虑的问题了。

那么,接下来,就用多线程 模拟 单例模式

hashCode 值相等话,代表指向同一地址

  1. 饿汉模式

那么 由以上 结果 可知

饿汉模式的 单例 是可以满足 多线程的

       2 懒汉模式

那么 由以上 结果 可知

懒汉模式的 单例 是不可以满足 多线程的(未加锁)

附:以上的谈谈,都是适合一般情况,如果是对其中的加锁,结果又会是另外一种情况,对于锁机制,到时到后期的 高并发再来好好谈谈,这里就先不做深究~

       夜阑珊,读无眠,听尽春言盎然处

      作为小白的自己,现在已经毕业两年了,岁月早已经侵蚀了自己当初初入社会的青涩纯真。但是仍时刻保持激情,斗志满满,丝毫不敢有半点懈怠!

早上包子豆浆,挤着公交车地铁匆忙上班,

下班不敢早走,就怕工作没做好,交付质量不满意。

我不累,因为我有梦想,我的梦想 ,就是成为更好的自己!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值