Java之单例模式

//方法没有同步,调用效率高

public static SingletonDome01 getInstance() {

return instance;

}

}

懒汉式实现(单例对象延迟加载)

=============================================================================

要点: lazy load! 延迟加载, 懒加载! 真正用的时候才加载!

问题:资源利用率高了。但是,每次调用getInstance()方法都要同步,并发效率较低。

package com.ahzy;

/**

  • 单例懒汉式

  • @author 晓宇码匠

  • 资源利用率高。但是每次调用getIntance()都要同步,并发效率低

  • 当创建实例的代价较大时,用懒汉式

*/

public class SingletonDome02 {

private static SingletonDome02 instance;

private SingletonDome02() {

}

//方法同步,调用效率低

public static synchronized SingletonDome02 getInstance(){

//延迟加载,懒加载,真正用的时候再加载

if(instance==null){

instance = new SingletonDome02();

}

return instance;

}

}

双重检测锁实现

=====================================================================

要点:这个模式将同步内容下方到if内部,提高了执行的效率不必每次获取对象时都进行同步,只有第一次才同步创建了以后就没必要了。

问题: 由于编译器优化原因和JVM底层内部模型原因,偶尔会出问题。不建议使用。

package com.ahzy;

/**

  • 单例双重检测锁模式

  • @author 晓宇码匠

  • 问题:由于编译器优化原因和JVM底层模式内部原因,偶尔会出现数据调整问题,不建议使用

*/

public class SingletonDome03 {

private static SingletonDome03 instance = null;

private SingletonDome03() {}

/*

  • 这个模式将同步内容下方到if内部,提高了执行的效率

  • 不必每次获得对象时都要进行同步,只有第一次才同步

  • 创建了以后就没必要了。

*/

public static SingletonDome03 getInstance() {

if (instance == null) {

SingletonDome03 sc;

synchronized (SingletonDome03.class) {

sc = instance;

if (sc == null) {

synchronized (SingletonDome03.class) {

if (sc == null) {

sc = new SingletonDome03();

}

}

instance=sc;

}

}

}

return instance;

}

}

静态内部类实现方式(也是一种懒加载方式)

==================================================================================

要点:

  • 外部类没有static属性,则不会像饿汉式那样立即加载对象。

  • 只有真正调用getInstance(),才会加载静态内部类。加载类时是线程 安全的。 instance是static final类型,保证了内存中只有这样一个实例存在,而且只能被赋值一次,从而保证了线程安全性。

  • 兼备了并发高效调用和延迟加载的优势!

package com.ahzy;

/**

  • 静态类部类(也是一种懒加载)

  • @author 晓宇码匠

  • 特点:延迟加载,调用效率高,线程安全

*/

public class SingletonDome04 {

private static class SingletClassInstance{

private static SingletonDome04 instance = new SingletonDome04();

}

private SingletonDome04(){

}

public static SingletonDome04 getInstance(){

return SingletClassInstance.instance;

}

}

枚举实现单例模式

======================================================================

优点:

  • 实现简单.

  • 枚举本身就是单例模式。由JVM从根本上提供保障!避免通过反射和反序列化的漏洞!

缺点:无延迟加载.

package com.ahzy;

/**

  • 单例枚举式

  • @author 晓宇码匠

  • 优点:简单

  • 缺点:没有延迟加载

*/

public enum SingletonDome05 {

//这个枚举元素,本身就是单例模式

INSTANCE;

//添加自己需要的操作

public void singletonOperation() {

}

}

测试

================================================================

package com.ahzy;

public class Client {

public static void main(String[] args) {

SingletonDome01 s1 = SingletonDome01.getInstance();

SingletonDome01 s2 = SingletonDome01.getInstance();

System.out.println(s1);

System.out.println(s2);

System.out.println(SingletonDome05.INSTANCE==SingletonDome05.INSTANCE);

}

}

结果:

com.ahzy.SingletonDome01@15db9742

com.ahzy.SingletonDome01@15db9742

true

破解单例

==================================================================

方法:反射和反序列化(不包含枚举式)

预防操作(这个一般会在开发jdk或一些jar包的时候会去用):

  • 反射可以破解上面几种(不包含枚举式)实现方式!(可以在构造方法中手动抛出异常控制)

  • 可以通过定义readResolve()防止获得不同对象。

  • 反序列化时,如果对象所在类定义了readResolve(),(实际是一种回调),定义返回哪个对象。

public class SingletonDemo01 implements Serializable {

private static SingletonDemo01 s;

private SingletonDemo01() throws Exception {

if (s != null) {

throw new Exception(“只能创建一个对象”);

// 通过手动抛出异常,避免通过反射创建多个单例对象!

}

} // 私有化构造器

public static synchronized SingletonDemo01 getInstance() throws Exception {

if (s == null) {

s = new SingletonDemo01();

}

return s;

}

// 反序列化时,如果对象所在类定义了readResolve(),(实际是一种回调),定义返回哪个对象。

private Object readResolve() throws ObjectStreamException {

return s;

}

}

总结

================================================================

  • 效率
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值