Java单例模式注解是什么_深入灵魂的考验,每行注释都是灵魂的单例模式,源码+实例降临...

不管是设计模式也好,别的模式也要,他都是为了解决问题而发明的有效的方法。除了我们已经熟悉的23种设计模式以外,还有MVVM、Combinator等其它的东西,都已经是前辈们经过多年的摸爬滚打总结出来的,其有效性不容置疑。我这篇文章也不会用来证明设计模式是有用的,因为在我看来,这就跟1+1=2一样明显(在黑板上写下1+1=2)

而这,在现在这个追求高质量代码的时代,虽然显得有一些复杂,但是我个人还是“推崇”(看好了,我有引号的)这个东西,毕竟面试必问系列,你咋整

来看今天的内容吧,有代码,有实例,并且有一些内容我直接放在代码中通过注释进行讲解,会更好理解

文章首发公众号:Java架构师联盟,每日更新技术好文

一、设计部分:单例的实现思想、代码及注意问题

package com.test.hibernate;

/*生成一个懒汉式单例的基础理解:

1.Singleton顾名思义就是只能创建一个实例对象。。所以不能拥有public的构造方法

2.既然构造方法是私有的,那么从外面不可能创建Singleton实例了。。只能从内部创建。。所以需要一个方法来创建此实例,也因此只能通过类名来创建对象。。此方法肯定必须是static的

3.静态的getInstance方法要返回一个Singleton实例。。就要一个Singleton类型的变量来存储。。声明一个Singleton类型的属性。。同样需要是static 的。。静态方法只能访问静态属性。。。

!!!前3步是单例的共性!后三步是懒汉式需要考虑的地方!

4.为了保证只生成一个实例,需要做判断是否为null

5.此时考虑线程问题,假设有两个线程。。thread1,thread2。。thread1运行到判断那个Singleton类型的变量是否为null,然后跳到了thread2。。也运行到判断之后。。。此时两线程都得到single为空。。。那么就会有两个实例了。。。解决办法。。同步

6.同步又要考虑效率,不能有太多的没用同步

* */

//思考总结:其实饿汉式没什么问题,问题就是出现在懒汉式上,一般就是牵扯到执行效率和线程安全2个角度上来思考

//个人感觉 如果是饿汉式就用天然的没毛病,如果想用懒汉式就用静态内部类方式吧

//存在问题:如何在2个jvm上保证单例还未解决:这个就牵扯到分布式锁,可以用zookeeper来实现

//还缺少一种懒汉式的枚举方式实现有待研究,听说这个方法也不错。

public class danli { //模拟一下静态代码块的使用方式,静态代码块在类加载的运行,先静态代码块》再构造代码块》再构造函数 ,只研究单例可以忽略

public static final String STR1;

static {

STR1 = new String("zzh");

}

}

//下面正式演示各种单例的实现:

class danli2{//单例饿汉式(非延时加载),提前加载,有利于速度和反应时间,天然的线程安全的。没毛病

private danli2(){};

private static final danli2 two = new danli2();//final可加可不加,final的目的就是最终的,只允许一次赋值,但不加是因为没法在本类外给他赋值了,因为构造方法是私有的没法创建这个类的对象了,而且这个成员变量也是私有的所以不能在外面调用到,但是可以在本类中的其他方法调用到,所以其实还是可以修改的,所以还是加上final吧

public static danli2 getSingleInstance(){

return two;

}

}

class danli3{ //单例懒汉式(延时加载),用的时候再去加载,有利于资源充分利用

private danli3(){};

private static danli3 three = null;

public static synchronized danli3 getSingleInstance(){//加上synchronized变得线程安全了,但是效率下降了,每次还需要检查同步等等

if(three == null){//保证只生成一个实例

three = new danli3();

}

return three;

}

}

/* 该类跟上面那个是一样的,上面是synchronized方法,下面这个是代码块。

class Singleton {

private Singleton() {}

private volatile static Singleton instance = null;

public static Singleton getInstance() {

synchronized (Singleton.class) {//利用synchronized代码块,每次需要先检查有没有同步锁,效率较低,为了解决这个问题又提出了加入双层检查,也就是在这个同步代码块的外面再加一层为null判断,来减少除第一次以外的同步检查,提高了效率

if (instance == null) {

instance = new Singleton();

}

}

return instance;

}

}

*/

双重检查加锁就是在同步代码块的外面一层再来一个== null的判断,解决除第一次以外所有的同步判断导致的效率下降问题

//但是这个双重检查加锁在多线程环境下存在系统崩溃的可能(一个线程初始化一半的对象,被第二个线程直接拿去用了,所以系统崩溃了)

/*原因如下

1、线程 1 进入 getInSingleton() 方法。

2、由于 uniqueInstance 为 null,线程 1 在 //1 处进入 synchronized 块。

3、线程 1 前进到 //3 处,但在构造函数执行之前,使实例成为非 null。

4、线程 1 被线程 2 预占。

5、线程 2 检查实例是否为 null。因为实例不为 null,线程 2 将 uniqueInstance 引用返回给一个构造完整但部分初始化了的 Singleton 对象。

6、线程 2 被线程 1 预占。

7、线程 1 通过运行 Singleton 对象的构造函数并将引用返回给它,来完成对该对象的初始化。

*/

class Singleton {//双重检查加锁,线程相对安全了,避开了过多的同步(因为这里的同步只需在第一次创建实例时才同步,一旦创建成功,以后获取实例时就不需要同获取锁了),效率比上面那个能提高一些

// volatile关键字确保当uniqueInstance变量被初始化成Singleton实例时,多个线程正确地处理uniqueInstance变量,这个关键字其实也解决了上面说的系统可能崩溃的问题,因为使用这个变量也需要一个线程一个线程的来使用了

private volatile static Singleton uniqueInstance;

private Singleton() {

}

public static Singleton getInSingleton() {

if (uniqueInstance == null) {// 检查实例,如是不存在就进行同步代码区

synchronized (Singleton.class) {//1 // 对其进行锁,防止两个线程同时进入同步代码区

if (uniqueInstance == null) {//2 // 双重检查,非常重要,如果两个同时访问的线程,当第一线程访问完同步代码区后,生成一个实例;当第二个已进入getInstance方法等待的线程进入同步代码区时,也会产生一个新的实例

uniqueInstance = new Singleton();//3

}

}

}

return uniqueInstance;

}

// ...Remainder omitted

}

//使用静态内部类是没问题的,而且效率也不会降低,而且还是懒加载

class Singleton2 {//jvm加载SingletonHolder的时候会初始化INSTANCE,所以既是lazy的又保证是单例的

private static class SingletonHolder {//静态内部类,只会被加载一次(在加载外部类的时候),所以线程安全,注意静态只能使用静态

static final Singleton2 INSTANCE = new Singleton2();

}

private Singleton2 (){}//静态构造方法

public static Singleton2 getInstance() {//对外提供单例的接口

return SingletonHolder.INSTANCE;

}

}

class ceshi{//只是简单测试了一下单例,都为true,可以忽略

public static void main(String[] args) {

System.out.println(danli.STR1 == danli.STR1);//true

System.out.println(danli2.getSingleInstance() == danli2.getSingleInstance());

.........

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值