作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO
联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬
学习必须往深处挖,挖的越深,基础越扎实!
阶段1、深入多线程
阶段2、深入多线程设计模式
阶段3、深入juc源码解析
码哥源码部分
码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】
码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】
码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】
码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】
打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】
4-2-1、LifecycleStrategy
LifecycleStrategy接口按照字面的理解是一个关于Camel中元素生命周期的规则管理器,但实际上LifecycleStrategy接口的定义更确切的应该被描述成一个监听器:
当Camel引用程序中发生诸如Route加载、Route移除、Service加载、Serivce移除、Context启动或者Context移除等事件时,DefaultCamelContext中已经被添加到集合“lifecycleStrategies”(java.util.List)的LifecycleStrategy对象将会做相应的事件触发。
读者还应该注意到“lifecycleStrategies”集合是一个CopyOnWriteArrayList,我们随后对这个List的实现进行讲解。以下代码展示了在DefaultCamelContext添加Service时,DefaultCamelContext内部是如何触发“lifecycleStrategies”集合中已添加的监听的:
......
private void doAddService(Object object, boolean closeOnShutdown) throws Exception {
......
// 只有以下条件成立,才需要将外部来源的Object作为一个Service处理
if (object instanceof Service) {
Service service = (Service) object;
// 依次连续触发已注册的监听
for (LifecycleStrategy strategy : lifecycleStrategies) {
// 如果是一个Endpoint的实现,则触发onEndpointAdd方法
if (service instanceof Endpoint) {
// use specialized endpoint add
strategy.onEndpointAdd((Endpoint) service);
}
// 其它情况下,促发onServiceAdd方法
else {
strategy.onServiceAdd(this, service, null);
}
}
// 其它后续处理
......
}
}
......
4-2-2、CopyOnWriteArrayList与监听者模式
正如上一小节讲到的,已在DefaultCamelContext中注册的LifecycleStrategy对象存放于一个名叫“lifecycleStrategies”的集合中,后者是CopyOnWriteArrayList容器的实现,这是一个从JDK 1.5+ 版本开始提供的容器结构。
各位读者可以设想一下这样的操作:某个线程在对容器进行写操作的同时,还有另外的线程对容器进行读取操作。如果上述操作过程是在 没有“线程安全”特性的容器 中进行的,那么可能出现的情况就是:开发人员原本想读取容器中 i 位置的元素X,可这个元素已经被其它线程删除了,开发人员最后读取的 i 位置的元素变成了Y。但是在具有“写线程安全”特性的容器中进行这样的操作就不会有问题:因为写操作在另一个副本容器中进行,原容器中的数据大小、数据位置都不会受到影响。
如果上述操作过程是在 有“线程安全”特性的容器 中进行的,那么以上脏读的情况是可以避免的。但是又会出现另外一个问题:由于容器的各种读写操作都会加上锁(无论是悲观锁还是乐观锁),所以容器的读写性能又会收