单例模式

本文详细介绍了单例模式的实现方式,包括延迟实例化、同步方法、急切实例化、双重检查加锁、静态内部类单例模式等。并讨论了序列化对单例的影响以及如何解决,最后还介绍了枚举实现单例的方法。

单例模式:确保一个类只有一个实例,并提供访问这个实例的全局点。常用来管理共享的资源,例如:数据库连接或者线程池。

[]类图

这里写图片描述

[]单例模式的实现

()延迟实例化

public class Singleton {

private static Singleton uniqueInstance;

private Singleton() {

}

public static Singleton getInstance() {
    if (uniqueInstance == null) {
        uniqueInstance = new Singleton();
    }

    return uniqueInstance;
}

}

延迟实例化适用于单线程环境,它不是线程安全的,引入多线程时,就必须通过同步来保护getInstance(),否则可能会返回Singleton两个不同实例。比如,一个线程在判断uniqueInstance为null后,还没来得及创建新的Singleton对象,另一个线程此时也判断到uniqueInstance为null,这样两个线程便会创建两个Singleton实例。

[]处理单例模式的多线程

(1)同步方法

public class Singleton {

private static Singleton uniqueInstance;

private Singleton() {

}

public static synchronized Singleton getInstance() {
    if (uniqueInstance == null) {
        uniqueInstance = new Singleton();
    }
    return uniqueInstance;
}

}

增加synchronized 关键字,迫使每个线程在进入方法之前,要等待别的线程执行完方法,也就是说,不会有两个线程可以同时进入这个方法。这样会降低性能。

其实只有第一次执行此方法时,才真正需要同步。也就是说,一旦设置好uniqueInstance变量,就不需要同步这个方法。之后的每次同步都是多余。

(2)急切实例化

public class Singleton {

private static Singleton uniqueInstance = new Singleton();

private Singleton() {

}

public static Singleton getInstance() {
    return uniqueInstance;
}

}

优点:线程安全,在类加载的同时已经创建好了一个静态对象(创建的唯一对象)。

缺点:资源利用效率不高,可能该实例并不需要,但也被系统加载了。另外,在一些场景下是无法使用的,比如,如果Singleton实例的创建依赖参数或配置文件,则在getInstance()之前必须调用某个方法来设置这些参数,但在设置之前,可能已经创建了Singleton实例,这种情况下是无法使用的。

(3)双重检查加锁

public class Singleton {

private volatile static Singleton uniqueInstance;

private Singleton() {

}

public static Singleton getInstance() {
    if (uniqueInstance == null) {
        synchronized (Singleton.class) {
            if (uniqueInstance == null) {
                uniqueInstance = new Singleton();
            }
        }
    }

    return uniqueInstance;
}

}

()第一次判断是为了避免不必要的同步,第二次判断是为了在null的情况下创建实例。

假设线程A执行到 uniqueInstance = new Singleton()语句,这看起来是一条语句,但实际上它并不是一个原子操作,这句代码最终会编译成多条汇编指令,它大致做了3件事情:
(1)给Singleton的实例分配内存
(2)调用Singleton()的构造函数,初始化成员字段
(3)将uniqueInstance对象指向分配的内存空间

但是,由于 Java编译器允许处理器乱序执行,以及JDK1.5之前JVM中的Cache,寄存器到主内存回写顺序的规定,上面的第二和第三的顺序是无法保证的,也就是,执行顺序可能是1–2–3,也可能是1–3–2,如果是后者,并且在3执行完毕,2未执行前,被切换到线程B,这时uniqueInstance因为已经在线程A内执行了第三点,uniqueInstance已经是非空了,所以,线程B直接取走uniqueInstance。再使用时就会出错。

在JDK1.5之后,官方调整了JVM。具体化volatile关键字,因此。JDK1.5之后只需要将uniqueInstance的定义改为

private volatile static Singleton uniqueInstance=null;

就可以保证uniqueInstance对象每次都是从主内存中读取,当然volatile或多或少也会影响新能,但考虑到程序的正确性,牺牲这点性能还是值得的。

()多线程下效率高,但是在高并发环境下也有一定的缺陷,虽然发生的概率很小。

(4)静态内部类单例模式

public class Singleton {

private Singleton() {

}

private static class InstanceHolder {
    private static final Singleton instance = new Singleton();
}

public static Singleton getInstance() {
    return InstanceHolder.instance;
}
}

(5)若Singleton实现了 Serializable接口,可以通过序列化将对象写入到磁盘中,然后再从磁盘中反序列化生成一个新的对象,这是两个不同的对象,这样违背了单例模式的初衷。

public class Singleton implements Serializable {

private Singleton() {

}

private static class InstanceHolder {
    private static final Singleton instance = new Singleton();
}

public static Singleton getInstance() {
    return InstanceHolder.instance;
}

/**
 * 反序列化时会自动调用
 *
 * @return
 * @throws ObjectStreamException
 */
private Object readResolve() throws ObjectStreamException {
    return InstanceHolder.instance;
}
}

这样反序列化时,就会自动调用readResolve()返回我们指定好的对象了,单例规则也就得到了保证。

()还可以采用枚举方式来实现单例模式

[]如果使用多个类加载器,可能会导致单例失效而产生多个实例。解决方案为:自行指定类加载器,并指定同一个类加载器。

内容概要:本文系统介绍了算术优化算法(AOA)的基本原理、核心思想及Python实现方法,并通过图像分割的实际案例展示了其应用价值。AOA是一种基于种群的元启发式算法,其核心思想来源于四则运算,利用乘除运算进行全局勘探,加减运算进行局部开发,通过数学优化器加速函数(MOA)和数学优化概率(MOP)动态控制搜索过程,在全局探索与局部开发之间实现平衡。文章详细解析了算法的初始化、勘探与开发阶段的更新策略,并提供了完整的Python代码实现,结合Rastrigin函数进行测试验证。进一步地,以Flask框架搭建前后端分离系统,将AOA应用于图像分割任务,展示了其在实际工程中的可行性与高效性。最后,通过收敛速度、寻优精度等指标评估算法性能,并提出自适应参数调整、模型优化和并行计算等改进策略。; 适合人群:具备一定Python编程基础和优化算法基础知识的高校学生、科研人员及工程技术人员,尤其适合从事人工智能、图像处理、智能优化等领域的从业者;; 使用场景及目标:①理解元启发式算法的设计思想与实现机制;②掌握AOA在函数优化、图像分割等实际问题中的建模与求解方法;③学习如何将优化算法集成到Web系统中实现工程化应用;④为算法性能评估与改进提供实践参考; 阅读建议:建议读者结合代码逐行调试,深入理解算法流程中MOA与MOP的作用机制,尝试在不同测试函数上运行算法以观察性能差异,并可进一步扩展图像分割模块,引入更复杂的预处理或后处理技术以提升分割效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值