循环日志
0 不允许在循环内打日志

1
主要策略:限制某个循环体内打日志的次数
主要困难:调用链太长,传递循环当前次数要改很多方法,类似于事务的connction,这种不方便传递参数的东西就想到了threadlocal
2 不想永久某线程到100就一直不让打了,想第二天的job清0
同时也不想用timer——threadlocal对象可析构——决定了要使用非static threadlocal对象——且threadlocal对象所在的bean不能单例,因为单例在ioc中往往不会释放,同时多例也有利于同一个线程处理不同业务的loop时能两边都打印,因为bean很可能不同,threadlocal不同,像(mybatis Guice 事务源码解析)

3 多例是否能真正解决问题?
3.1 多例在ioc的本质
定义:对一个bean的每次请求创建一个新实例
疑问:什么叫请求,a)装配时 b)调用bean的某个方法时
结论:请求指装配时,在将b塞入A的对象时即已确定,没有方法能让两次调用xxx的b对象是不同对象
证明:
Class A {
@Inject B b;
func main() {
for() {
handleitem() {
}
}
func handleitem() {
// print b hashcode here, all same, so ioc is lie
b.xxx();
// print b hashcode here again
b.xxx();
}
}
3.2 我们的场景
job today -
A a1 = getClass(A.class);
a1.main();
in a1:
class A
inject B b1 - in B, inject limit1
Inject C c1 - in C, Inject limit2
main() {
new Thread [] {
b.xxx();c.xxx(); both b and c will print top N because different threadLocal object
}
}
}
a1/b1/c1/limit1/limit2 all get released during gc
job tomorrow -
A a2 = getClass(A.class); get another A object
in a2
inject B b2 - in B, inject limit3
Inject C c2 - in C, Inject limit4
a2.main(), in this call, everything is new
要想threadlocal被释放,threadlocal所在bean要能释放,进而装配该bean的调用源头以多例的形式来调用,
在我们这里,是loader = guice.getClass(Loader),那么就要保证loader指向的那个对象能被回收,而不是被工厂保存起来
4 代码


5 测试

调用链1:可以看到多线程各自计数

调用链1的threadlocal被回收,调用链2的threadlocal被创建并回收

再次调用链2,threadlocal被回收,从侧面证明了gui调用链也是多例

LoggerCounter 7个没回收,预期内:ThreadLocal内存泄漏问题实践(二)

第一次gc后,CounterThreadLocal对象还在,因为我们override了finalize方法,所以没有导致回收,只是重新加入回收队列,第2次gc后回收:java finalize及实践
5 tiny修改20241125

6 性能
一亿次调用printLog()

qps(亿)
1: 1.04
10: 1.86
100:1.91
200: 1.98
业务端流量为每秒10000 << 2yi
组合qps= 10000/(1+10000*1/2yi)=1/(1/10000+1/2yi)
7 用完了次数后,能不能显式把threadlocal=null,这样threadlocalmap就能直接空出来,不用依赖gc
不能,因为只是这个线程用完了
同时不用担心map的容量而提前手动回收,jdk会扩容,且200个threadlocal对象的性能跟1个也差不多
8 假如我就要一个线程达到limit后就停止,不顾其他线程了,要不要volatile修饰threadlocal对象?
1)当第一条线程 threadlocal=new endthreadlocal后,第二条线程getthreadlocal().get(),threadlocal理论上应该有延迟,另外一条线程的副本指到原本的threadlocal对象,这条强引用链是有可能存在一段时间的,如果考虑高精度时效,理论上可以用volatile强制刷新
9 test case

浙公网安备 33010602011771号