JAVA进阶 THREAD学习09 多线程案例--单例模式

单例模式

总结下单例模式的基本框架:

  1. 私有静态的类内部声明(private static )

私有的声明实现了类的单一声明,只能在类的内部声明这个类,在类的外部不能声明。

  1. 私有构造方法(private)

私有构造实现了类的单一实例化(new),只能在本类里面实例化,避免外部的实例化。

  1. 公共静态访问方法(public static)

这是单例类的唯一外部访问方法,只有这个方法才能获取该类的信息。

饿汉模式

饿汉因为饿所以行动非常急切,这个形象的说法对应在单例模式中就是,类在声明的时候就直接实例化。对应到代码上,就是 (变量类型 变量名=new 变量类型)。

class SingleMode{
    private static SingleMode singleMode=new SingleMode();
    private SingleMode(){};
    public static SingleMode getItem(){
        return singleMode;
    }
}

懒汉模式-单线程版

class SingleMode2{
    private static SingleMode2 singleMode2=null;
    private SingleMode2(){};
    public static SingleMode2 getItem(){
        if(singleMode2==null){
            singleMode2=new SingleMode2();
        }
        return singleMode2;
    }
}

懒汉模式-多线程版

多线程版就比单线程多了一个synchronized同步锁(互斥锁),他保证了每次只有一个线程可以访问这个类。用一个比较好理解的例子来说明:

  • 有很多个男生喜欢校花(多个线程)
  • 他们知道了校花还没有男友(singleMode3==null)
  • 于是他们都争着去追求校花,不过校花是有原则的,只能竞争机会(竞争同步锁,竞争到同步锁的可以执行)(synchronized)
class SingleMode3{
    private static SingleMode3 singleMode3 =null;
    private SingleMode3(){};
    public synchronized static SingleMode3 getItem(){
        if(singleMode3 ==null){
            singleMode3 =new SingleMode3();
        }
        return singleMode3;
    }
}

懒汉模式-多线程版进阶

进阶版增加了两个关键的点

  • volatile确保对象可见性
  • 双 if() 确保线程单一准确访问

继续用上面一个例子来说明:

  • 有很多个男生喜欢校花(多个线程)
  • 他们知道了校花还没有男友(外层 if(singleMode4=null)判断singleMode4是否实例化)
  • 他们一部分人已经可以接触校花(执行getItem())
  • 不过校花是有原则的,这一部分人只能竞争单一机会(竞争同步锁,线程竞争到同步锁的可以执行代码)(synchronized)
  • 这时A竞争到了单一机会,通过接触了解校花确实还没有男朋友(内层 if(singleMode4=null)判断是否实例化)
  • 接着发展顺利就和校花初成了(new singleMode4() )
  • 可以接触校花的那一部分人在A离开后进一步判断(内层 if(singleMode4==null)判断是否实例化)
  • 这时他们知道校花已经和A处成了,就只能愤愤地离开(内层判断返回false)
  • 没办法接触校花的人得知传闻也打消了念头(外层判断返回flase)

外层 if 是反应比较慢还没有执行getItem方法的线程判断是否实例化
内层 if 是已经执行getItem方法的、已经在竞争同步锁的线程判断是否实例化
双层 if 判断确保了整个项目只会实例化一个对象。

class SingleMode4{
    private volatile static SingleMode4 singleMode4 =null;
    private SingleMode4(){};
    public static SingleMode4 getItem(){
        if(singleMode4 ==null){
            synchronized(singleMode4){
                if(singleMode4==null){
                    singleMode4 =new SingleMode4();
                }
            }
        }
        return singleMode4;
    }
}

这对于日志记录、驱动程序对象、缓存、线程池、数据库连接等特别有用,在这些情况下,拥有多个实例可能会导致不一致或效率低下。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值