使用ThreadLocal请务必remove

 

特别注意,web容器的线程是重复使用的,web容器使用了线程池,当一个请求使用完某个线程,该线程会放回线程池被其它请求使用,这就导致一个问题,不同的请求还是有可能会使用到同一个线程(只要请求数量大于线程数量),而ThreadLocal是属于线程的,

如果我们使用完ThreadLocal对象而没有手动删掉,那么后面的请求就有机会使用到被使用过的ThreadLocal对象!

这时候分情况考虑了:

1此请求在使用ThreadLocal的时候,是先get()来判断然后再set(),那就会有问题。因为get到的是别的请求set的内容,

2此请求在使用ThreadLocal,都是先set再get,那就不会有问题,因为一个线程同一时刻只被一个请求使用,只要我们每次使用之前,都设置成自己想要的内容,那就不会在使用的过程中被覆盖。

使用ThreadLocal最好是每次使用完就调用remove方法,将其删掉,避免先get后set的情况导致业务的错误。

 

第二点,不remove的话容易造成堆栈内存溢出。

 

线程池重用线程时,会对ThreadLocal的值进行清空吗?

 

 

《Java并发编程实战》一书的第8章时,有如下一句话:

 

只有当线程本地值的生命周期受限于任务的生命周期时,在线程池的线程中使用ThreadLocal才有意义,而在线程池的线程中不应该使用ThreadLocal在任务之间传递值。

 

------------

不会清空,要你自己去清空。

ask指的是一个Thread所执行的任务。

总之就是告诉你,如果你能够在使用ThreadLocal的时候管理它的创建、销毁,那么就可以用,否则会出问题。原因是ThreadLocal是和Thread绑定的,如果Thread是从Thread Pool中拿出来的,那么意味着Thread可能会被复用,如果被复用,你就一定得保证这个Thread上一次结束的时候,其关联的ThreadLocal被清空掉,否则就会串到下一次使用。

 

posted @ 2021-08-05 21:15  panchanggui  阅读(3944)  评论(0编辑  收藏  举报