时间总是过得飞快,每天奔波于工作与生活的天平两端的起跑线,总要二者兼顾,生怕哪一端会有倾斜。如此小白,怕有何用?
这是自己的第二篇原创文章了,其实说心里话,自从昨天写的第一篇文章,得到了一定的认可,也有大家的关注,自己内心心里真的是满满的感动。原创不易,且行且珍惜,有大家的支持,自己一定会更加用心写,回馈给大家每天愿意花的几分钟阅读自己的文章,在这里,再次表示感谢。愿我们的关注,永不散场。同时,自己内心心里隐约深处总会有这么一个声音,会对自己说:作为铁打的小白,你有什么干货,有什么吞吐量输出的呢?写文章花费的时间,还不如自己多看看书,多看看学习视频,如此小白,何必这样?
马老师前天说过,青山不改,绿水长流,让我们江湖再见!每个人都会有选择,马老师也做了他自己的选择,而我既然选择写,就会自己只要有好的想法心得,就会愿意花时间写写,跟大家交流交流。在如今互联网快速发展的时代,自己的往前一步会迈向何方?自己的往后退一步又会停留在哪里?面对着生活的些许琐事,已经够烦了,心还不安稳。既然认定了一条路,勇敢的走下去就是了,更何况有支持自己的人,如此小白,何必庸人自扰?
一颗心,心如止水,上善若水,用不凡的心征服自己!小白坚信,小白也会有春天,重回首,去时年,揽尽风雨苦亦甜!
好了,话不多说,直接来干吧,进入这次的主题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 在初始化的时候就 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 值相等话,代表指向同一地址
饿汉模式
那么 由以上 结果 可知
饿汉模式的 单例 是可以满足 多线程的
2 懒汉模式
那么 由以上 结果 可知
懒汉模式的 单例 是不可以满足 多线程的(未加锁)
附:以上的谈谈,都是适合一般情况,如果是对其中的加锁,结果又会是另外一种情况,对于锁机制,到时到后期的 高并发再来好好谈谈,这里就先不做深究~
夜阑珊,读无眠,听尽春言盎然处
作为小白的自己,现在已经毕业两年了,岁月早已经侵蚀了自己当初初入社会的青涩纯真。但是仍时刻保持激情,斗志满满,丝毫不敢有半点懈怠!
早上包子豆浆,挤着公交车地铁匆忙上班,
下班不敢早走,就怕工作没做好,交付质量不满意。
我不累,因为我有梦想,我的梦想 ,就是成为更好的自己!