博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ThreadLocal与线程池使用的问题
阅读量:7096 次
发布时间:2019-06-28

本文共 2963 字,大约阅读时间需要 9 分钟。

感谢博主的这篇分享,见 

在今天的面试中,突然被考官问了这个问题,当时脱口而出的是 threadlocal容易会有内存泄漏,需要注意remove。其实自己仔细想想,这个回答太过于结果了,没有思考为何要配合线程池的时候,去remove。

 

注意,这里需要你的jdk版本为1.8及以上,否者清将lambda表达式改为匿名内部类

 

问题的版本

1 public class ThreadLocalAndPool { 2  3     /** 4      * jdk8 的语法 5      */ 6     private static ThreadLocal
variableLocal = ThreadLocal.withInitial(() -> 0); 7 8 public static int get() { 9 return variableLocal.get();10 }11 12 public static void remove() {13 variableLocal.remove();14 }15 16 public static void increment() {17 variableLocal.set(variableLocal.get() + 1);18 }19 20 public static void main(String[] args) {21 ExecutorService executorService = new ThreadPoolExecutor(2,2,0, TimeUnit.SECONDS,new LinkedBlockingDeque<>(12));22 23 for(int i=0;i<5;i++){24 executorService.execute(()->{25 long threadId = Thread.currentThread().getId();26 27 int before = get();28 increment();29 int after = get();30 System.out.println("threadid " + threadId +" before " + before + ", after " + after);31 });32 }33 34 executorService.shutdown();35 }36 37 38 }

得到的结果

threadid 12 before 0, after 1

threadid 13 before 0, after 1
threadid 12 before 1, after 2
threadid 13 before 1, after 2
threadid 12 before 2, after 3

 

这个其实就是threadlocal与线程池使用的问题了,因为threadlocal维护是 Map<Thread,T>这个结构,而线程池是对线程进行复用的,如果没有及时的清理,那么之前对该线程的使用,就会影响到后面的线程了,造成数据不准确。

 

修正的版本,就是加一个remove

1 public class ThreadLocalAndPool { 2  3     /** 4      * jdk8 的语法 5      */ 6     private static ThreadLocal
variableLocal = ThreadLocal.withInitial(() -> 0); 7 8 public static int get() { 9 return variableLocal.get();10 }11 12 public static void remove() {13 variableLocal.remove();14 }15 16 public static void increment() {17 variableLocal.set(variableLocal.get() + 1);18 }19 20 public static void main(String[] args) {21 ExecutorService executorService = new ThreadPoolExecutor(2,2,0, TimeUnit.SECONDS,new LinkedBlockingDeque<>(12));22 23 for(int i=0;i<5;i++){24 executorService.execute(()->{25 try {26 long threadId = Thread.currentThread().getId();27 28 int before = get();29 increment();30 int after = get();31 System.out.println("threadid " + threadId +" before " + before + ", after " + after);32 }33 finally {34 remove();35 }36 });37 }38 39 executorService.shutdown();40 }41 42 43 }

上面运行的结果如下(不同机器的threadid会有所不同)

threadid 12 before 0, after 1

threadid 13 before 0, after 1
threadid 12 before 0, after 1
threadid 13 before 0, after 1
threadid 13 before 0, after 1

 

转载于:https://www.cnblogs.com/westlin/p/10645217.html

你可能感兴趣的文章
JAVA第一周学习
查看>>
sql语句select group by order by where一般先后顺序 转载
查看>>
for循环是怎么工作的
查看>>
iPhone 上怎么给CSS定义 active 样式
查看>>
tomcat+mysql安装配置,项目部署(上)
查看>>
linux sysrq
查看>>
(转)as3数组的深复制和浅复制
查看>>
HTML5/CSS3系列教程:HTML5 区域(Sectioning)的重要性
查看>>
Spring Batch学习笔记
查看>>
asp.net mvc 如何在执行完某任务后返回原来页面
查看>>
Windows的本地时间(LocalTime)、系统时间(SystemTime)、格林威治时间(UTC-Time)、文件时间(FileTime)之间的转换...
查看>>
hdu 2189
查看>>
std::map, std::multimap, std::tr1::unordered_map 区别 - 笔记本 - 博客频道 - CSDN.NET
查看>>
ASP.NET 自定义成员资格提供程序 Part.4(使用自定义提供程序类)
查看>>
苹果面试8大难题及答案
查看>>
jQuery 2.0.3 源码分析Sizzle引擎 - 超级匹配
查看>>
ubuntu中查看各种设备和资源的命令汇总
查看>>
Chrome好用的扩展插件
查看>>
封装jQuery Validate扩展验证方法
查看>>
Android之代码创建布局
查看>>