首页 > 编程知识 正文

threadlocal的值会在多线程间共享,threadlocal最佳实践

时间:2023-05-04 17:39:54 阅读:263226 作者:3258

在业务开发中,threadLocal有两种业务场景运用较多。

1、threadlocal保证每个线程独享对象,创建本地线程的副本,保证每个线程都拥有属于自己的副本,这样保证线程安全。

2、threadlocal可以作用类似全局变量,在其中一个方法里用set存入数据,其他方法可以用get直接获取,避免了传参,作用到每个线程独立保存信息。

场景一: //private static final Integer NUM = 0; private static final ThreadLocal<Integer> NUM = new ThreadLocal<Integer>(){ @Override protected Integer initialValue() { return 0; } }; public static void main(String[] args) { for (int i = 0; i < 3; i++) { Thread thread = new Thread() { @Override public void run() { add(); } }; thread.start(); } } private static void add() { for (int i = 0; i < 5; i++) { Integer n = NUM.get(); n++; NUM.set(n); System.out.println("当前线程:" + Thread.currentThread().getName() + "的[NUM]=" + n); } }

结果:开启了三个线程,因为用了threadlocal,每个线程都有属于自己的本地副本,并不会累加到15,而是n最大输出5。

还有就是simpledateformat也适用于场景一,当线程池开启,提交10000个或者更多任务时,每个线程都创建属于自己的simpledateformat开销会很大,而且占用内存,销毁对象也是有开销的:这种情况下,我们首先想到的是所有线程先共用一个simpledataformate,但他不是线程安全的,如何解决呢,给他加synchrolized锁,这样可以解决,但线程运行的时候,会发生阻塞,非常影响效率,此时此刻threadlocal就是非常好的解决办法。

threadlocal会让每个线程的simpledateformat独立,如果线程池Executors.newFixedThreadPool(15)开启15个线程,则只会创建15个simpledateformat,而且线程安全,相互之前不会影响。

场景二: //保证对象取出,不需要传参 public static void main(String[] args) { Dog dog = new Dog("缥缈的冬日"); new Service1().service1(dog); } static class Dog { String name; public Dog(String name) { this.name = name; } } static class DogThread { //创建ThreadLocal保存User对象 public static ThreadLocal<Dog> dogThreadLocal = new ThreadLocal<>(); } static class Service1 { public void service1(Dog dog) { //赋值 DogThread.dogThreadLocal.set(dog); new Service2().Service2(); } } static class Service2 { public void Service2() { //取值 System.out.println("service2:" + DogThread.dogThreadLocal.get().name); //记得移除 DogThread.dogThreadLocal.remove(); } }

场景二类似于全局变量,免去了传参的麻烦 ,保证方法得到的对象值相同,先将对象存储在localthread里面,然后在获取,最后一定要记得remove掉。

 

问:线程池中使用threadlocal为什么容易造成内存泄漏?

因为线程池里的线程存活周期太长,往往跟程序的停止才销毁的,这样threadlocal持有的threadlocalmap就一直不会被回收,解决办法,可以手动在finally块调用它的remove()方法。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。