内存泄漏事故(二)线程的中断不可信任【重要】配合volatile强制回收子线程成员变量
1
Map<k, list>
not good:
map.remove(k)
如果这时有其他指针指向list,则list无法释放
good:
map.get(k).clear()
map.remove(k)
即使这是有其他指针指向list,导致list无法释放,但是这个list是空的,泄漏的后果不严重
2 线程的中断不可信任
2.1 要确保清理到位给予线程的引用
怎么做?见3
2.2 避免无法从外部清理线程的资源
尽量不要用局部变量接收大对象,方法如果block了资源会被局部metho hold住,外部也没办法接触;
ex:
func(List list) {
List x = list;
for(Object o : x) {
do sth(o); // blocked, 如果这个do sth方法没有办法被打断,那么这个局部变量x会hold住一个list造成泄漏
}
}
用成员变量,+volatile,外部线程强制解绑

注意volatile修饰ref

可以看到确实可以确实可以强制回收,主线程的clear把子线程的成员变量强行刷成null
3 细节

再改一版

3.1.1 如果能进cancellation(理论上不会出现,因为没有对futureTask做cancel),说明子线程future一定已经接收了cancel的指令,至于是中断中还是中断完了,是否完成finally未知,因此要手动clear
子线程既已在中断中或中断完,则无需再次interrupt
而本线程无需interrupt一下,因为本线程并未接收到cancel或interrupte,因为如果接收了任一,则会进入Interrupted
3.1.2 习惯上必须设置timeout,避免本线程一直在那里等,timeout后清理掉资源和stop子线程
3.1.3 InterruptedException,说明有人在外边要stop本线程,那么清理掉资源,往下传递stop指令, future task cancel (二)向下传递中断
同时因为是进的InterruptedException,重新设置一下旗标
3.1.4 从future。get方法,如果不是cancellation和interrupted的其他异常,则fianally一定已经跑过了
3.1.5 其他exception也要clear一下,避免非子线程地方出现异常,但是资源已经给了子线程的情况
3.2 new操作时调用当前线程的类加载器,还是调用方的类加载器 (四)完美证明用例
当前线程类加载器,并不是当前线程的类由当前线程的类加载器加载,别搞错了
3.3 对3.1 所引用的那篇文章小结下
3.3.1 对子线程interrupt,父线程继续get,get什么取决于子线程怎么写的
3.3.2 对子线程cancel,父线程进cancellation
3.3.3 对子线程cancel,马上对父线程cancel,父线程进interrupted
3.3.4 对子线程cancel,隔一段时间对父线程cancel,父线程进cancellation
浙公网安备 33010602011771号