本文共 3370 字,大约阅读时间需要 11 分钟。
继上一篇: 目前已经在google code上新建了一个project,也在逐步的完善和加强并行加载的功能,这里记录一下ChangeLog。
相关代码: , 有兴趣的同学可以一起参与,目前正在公司的应用中打算实施,逐步的在完善功能和解决一些兼容性的问题。
AsyncLoadExecutor(并行加载的执行容器),修改了HandleMode模式,增加了CALLERUN,废弃了BLOCK。
HandleMode(针对并行加载队列满负荷时的一种处理模式):
为了异步并行加载,部分的代码块会由多个Thread执行,原先的ThreadLocal属性的模式已经不再有效。线程分为:caller thread(主线程,一般web应用为Jetty,Tomcat的Http工作线程) 和 runner thread(并行加载的执行线程)。
目前项目中支持在runner thread的可以正常获取ThreadLocal数据(caller thread运行中产生的ThreadLocal)。
简单设计:
ThreadLocal建议使用: 在异步加载中对ThreadLocal为只读,尽量不对其进行set操作。
伪代码:
1.try { 2. threadLocal.put(object); 3. serviceA.method(){ // 并行加载1 4. Object obj = threadLocal.get(); 5. } 6. serviceB.method(){ // 并行加载2 7. Object obj = threadLocal.get(); 8. } 9.} finally { 10. threadLocal.remove(object); 11.}
说明:
1. 在所有的并行加载执行之前,完成threadLocal的设置,在最后完成threadLocal的清理。
2. 在各个并行加载容器中读取threadLocal信息。
针对一下的几种场景,使用ThreadLocal潜在风险:
1. serviceB依赖serviceA的ThreadLocal属性put。 因为A和B都是在并行的加载,所以很难确定执行的前后顺序。
2. caller线程依赖serviceA的ThreadLocal的属性put,因为A是一个并行加载,所以caller可能会优先于serviceA调用threadLocal
3. serviceA和serviceB都各自进行ThreadLocal属性的设置,因为执行顺序的不确定性和多Thread的执行,所以最后需要在caller线程进行合并,可能导致数据会丢失
1. 允许在构造代理工程时,设置targetClass。允许自定义cglib代理的目标class,而不是自动扫描对应service的class对象。
2. 使用template提交代码"闭包"的方式。
修改代码类:AsyncLoadResult
增加了对timeout<=0的逻辑判断,如果<=0,则调用future.get()进行处理,不进行超时控制。
修改代码类:AsyncLoadConfig
原先默认超时时间为3000毫秒,但考虑在老系统上实施并行加载,程序员coding时意识不够,或者系统上线初期对timeout把握不够,所以这里考虑修改了默认的超时时间。
修改代码类:AsyncLoadResult
针对future.get(timeout, TimeUnit.MILLISECONDS); 针对出现TimeoutException时,需要进行cancel处理。
修改代码为:
1.try { 2. // 使用cglib lazyLoader,避免每次调用future 3. return future.get(timeout, TimeUnit.MILLISECONDS); 4. } 5. } catch (TimeoutException e) { 6. future.cancel(true); 7. throw e; 8.}
存在的注意点:
因为透明的进行了多线程机制,原先的正常业务中并不会去处理Thread.interrupt() 和 InterruptException。
可能出现的一种现象:
caller thread已经结束,但pool池中存在很多RUNNING的Thread线程。导致出现线程池不够用,该stop的没有stop。
解决方案:
待定。目前暂未想到比较好的处理方案,因为需要对一个RUNNING的Thread线程执行一个stop操作,原先的Thread.stop(Throwable e)已经被@Deprecated,具体原因:
为了支持复杂的业务系统,尽可能自适应。这里提供了一个增强Class.newInstance()方法。实现方式比较简单:
1.public static Object newInstance(Class type) { 2.// 1. 首先查找默认的空构造函数 3.// 2. 查找其他的构造函数,默认选取第一个 4.// 2.1 获取构造函数的参数类型,产生默认的参数值,处理原型和数组,对象等。 5.}
1.2. 3. 4. 5. 9.6.
8.asyncLoadTestServiceForInteceptor 7.10. 14.11.
13.asyncLoadInterceptor 12.
新增了两个接口类:
转载地址:http://uorlo.baihongyu.com/