threadlocal

来探讨一下最近面试问的ThreadLocal问题

最后都变了- 提交于 2019-12-04 05:51:48
中高级阶段开发者出去面试,应该躲不开ThreadLocal相关问题,本文就常见问题做出一些解答,欢迎留言探讨。 ThreadLocal为java并发提供了一个新的思路, 它用来存储Thread的局部变量, 从而达到各个Thread之间的隔离运行。它被广泛应用于框架之间的用户资源隔离、事务隔离等。 但是用不好会导致内存泄漏, 本文重点用于对它的使用过程的疑难解答, 相信仔细阅读完后的朋友可以随心所欲的安全使用它。 内存泄漏原因探索 ThreadLocal操作不当会引发内存泄露,最主要的原因在于它的内部类ThreadLocalMap中的Entry的设计。 Entry继承了 WeakReference<ThreadLocal<?>> ,即Entry的key是弱引用,所以key'会在垃圾回收的时候被回收掉, 而key对应的value则不会被回收, 这样会导致一种现象:key为null,value有值。 key为空的话value是无效数据,久而久之,value累加就会导致内存泄漏。 static class ThreadLocalMap { static class Entry extends WeakReference<ThreadLocal<?>> { Object value; Entry(ThreadLocal<?> k, Object v) { super(k); value =

聊聊高并发(二)结合实例说说线程封闭和背后的设计思想

心不动则不痛 提交于 2019-12-04 05:22:42
高并发问题抛去架构层面的问题,落实到代码层面就是多线程的问题。多线程的问题主要是线程安全的问题(其他还有活跃性问题,性能问题等)。 那什么是线程安全?下面这个定义来自《Java并发编程实战》,这本书强烈推荐,是几个Java语言的作者合写的,都是并发编程方面的大神。 线程安全指的是:当多个线程访问某个类时,这个类始终都能表现出正确的行为。 正确指的是“所见即所知”,程序执行的结果和你所预想的结果一致。 理解线程安全的概念很重要, 所谓线程安全问题,就是处理对象状态的问题 。如果要处理的对象是无状态的(不变性),或者可以避免多个线程共享的(线程封闭),那么我们可以放心,这个对象可能是线程安全的。当无法避免,必须要共享这个对象状态给多线程访问时,这时候才用到线程同步的一系列技术。 这个理解放大到架构层面,我们来设计业务层代码时,业务层最好做到无状态,这样就业务层就具备了可伸缩性,可以通过横向扩展平滑应对高并发。 所以我们处理线程安全可以有几个层次: 1. 能否做成无状态的不变对象。无状态是最安全的。 2. 能否线程封闭 3. 采用何种同步技术 我理解为能够“逃避”多线程问题,能逃则逃,实在不行了再来处理。 了解了线程封闭的背景,来说说线程封闭的具体技术和思路 1. 栈封闭 2. ThreadLocal 3. 程序控制线程封闭 栈封闭说白了就是多使用局部变量

Dubbo 全链路追踪日志的实现

社会主义新天地 提交于 2019-12-03 21:35:21
微服务架构的项目,一次请求可能会调用多个微服务,这样就会产生多个微服务的请求日志,当我们想要查看整个请求链路的日志时,就会变得困难,所幸的是我们有一些集中日志收集工具,比如很热门的ELK,我们需要把这些日志串联起来,这是一个很关键的问题,如果没有串联起来,查询起来很是很困难,我们的做法是在开始请求系统时生成一个全局唯一的id,这个id伴随这整个请求的调用周期,即当一个服务调用另外一个服务的时候,会往下传递,形成一条链路,当我们查看日志时,只需要搜索这个id,整条链路的日志都可以查出来了。 现在以dubbo微服务架构为背景,举个栗子: A -> B -> C 我们需要将A/B/C/三个微服务间的日志按照链式打印,我们都知道Dubbo的RpcContext只能做到消费者和提供者共享同一个RpcContext,比如A->B,那么A和B都可以获取相同内容的RpcContext,但是B->C时,A和C就无法共享相同内容的RpcContext了,也就是无法做到链式打印日志了。 那么我们是如何做到呢? 我们可以用左手交换右手的思路来解决,假设左手是线程的ThreadLocal,右手是RpcContext,那么在交换之前,我们首先将必要的日志信息保存到ThreadLocal中。 在我们的项目微服务中大致分为两种容器类型的微服务,一种是Dubbo容器,这种容器的特点是只使用spring容器启动

线程封闭

两盒软妹~` 提交于 2019-12-03 12:14:00
1.jdbc和servlet的例子 jdbc和servlet中,之所以是线程安全的,就是因为每个变量都封装在单个线程中,不会存在变量共享的状态,也就是说,你这一次获取的数据不会被下一个请求访问到,所以通过把变量都封闭在线程中,来达到了线程安全的目的.所以在servlet中使用 缓存 session 或者定义 static 等共享变量的时候就要小心,因为这些是多个线程所共享的,所以需要保证线程安全问题. 2.栈封闭 局部变量都封闭在执行线程中,只要不发布局部变量,就没有线程安全问题. public class SafeClass { public int safeMethod(Collection<String> collection) { //i被封装在的栈中,具体参考<深入理解java虚拟机> //i因为被封装在栈中,不会被别的线程访问到,所以也就保证了线程安全 int i = 0; i++; //sortedSet 同理,也被封闭在栈中,没有逸出,也不会被别的线程访问到 SortedSet<String> sortedSet = new TreeSet<String>(); sortedSet.addAll(collection); return i; } } 3.ThreadLocal类 ThreadLocal能使线程中的值和保存值的对象关联起来,比如 package

ThreadLocal小试牛刀

只谈情不闲聊 提交于 2019-12-03 07:24:50
ThreadLocal中保存的数据只能被当前线程私有,不被其它线程可见 证明 声明一个全局的变量 threadLocal ,初始值为 1 ,通过 3 个线程对其进行访问修改设置,理论上 threadLocal 的最终值应该是 6 ,然而我们的输出结果是 3 ,说明了 threadLocal 中存放的数据是各自线程私有的 java">package com.mmall.concurrency.example.threadLocal; public class UseThreadLocal { static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>() { @Override protected Integer initialValue() { return 1; } }; //运行3个线程 public void startThreadArray() { Thread[] thread = new Thread[3]; for (int i = 0; i < thread.length; i++) { thread[i] = new Thread(new MyThread(i)); } for (int i = 0; i < thread.length; i++) { thread[i].start();

ThreadLocal小试牛刀

我的梦境 提交于 2019-12-03 07:04:40
ThreadLocal中保存的数据只能被当前线程私有,不被其它线程可见 证明 声明一个全局的变量 threadLocal ,初始值为 1 ,通过 3 个线程对其进行访问修改设置,理论上 threadLocal 的最终值应该是 6 ,然而我们的输出结果是 3 ,说明了 threadLocal 中存放的数据是各自线程私有的 package com.mmall.concurrency.example.threadLocal; public class UseThreadLocal { static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>() { @Override protected Integer initialValue() { return 1; } }; //运行3个线程 public void startThreadArray() { Thread[] thread = new Thread[3]; for (int i = 0; i < thread.length; i++) { thread[i] = new Thread(new MyThread(i)); } for (int i = 0; i < thread.length; i++) { thread[i].start(); } }

Will the ThreadLocal object be cleared after thread returned to Thread Pool?

匿名 (未验证) 提交于 2019-12-03 03:06:01
可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试): 由 翻译 强力驱动 问题: Will the contents that are stored in the ThreadLocal storage during an execution be cleared automatically when the thread is returned to ThreadPool (as would be expected) ?? In my application I am putting some data in ThreadLocal during some execution but if next time the same Thread is being used, then I am finding the obsolete data in ThreadLocal storage. 回答1: The ThreadLocal and ThreadPool don't interact with one another unless you do this. What you can do is a a single ThreadLocal which stores all the state you want to hold and

从ThreadLocal的线程回收想到的

时光毁灭记忆、已成空白 提交于 2019-12-03 02:33:39
一、背景介绍 小弟最近做了一个管理后台操作记录落DB的小需求,实现过程中需要获取操作用户的登陆信息,但是登陆信息需要从公司另一个AD服务系统中通过RPC方式进行查询,为了既达到判断用户的登陆状态,又能够在CRUD中使用到登陆信息。本人实现的思路是,在CRUD请求到达Controller层前,使用拦截器捕获到请求,调用AD服务验证请求携带的Cookie信息是否有效,并且获取到用户的"账号、UID、其他基本信息",为了能够在Service层获取到这些基本信息,又不能再次去调用AD服务【调用过程比较耗时】,本人决定将用户态信息保存到ThreadLocal中,这样在同一个线程中的方法都可以访问到。、 实现起来没有问题,但是小弟突然想到,线程执行完毕后,这个线程对应的用户态信息还会存在吗,是否会被JVM自动回收,如果不被即时回收,大量的CRUD会不会影响服务器的内存。并且为了将之前粗略浏览过一遍的《深入理解JVM虚拟机》进行实践,引发了本题。即”ThreaLoacl的内存结构深入剖析“+”ThreadLocal的垃圾回收机制是怎样进行的” 二、ThreadLocal原理 2.1ThreadLocal概述 2.2ThreadLocal的结构 2.3ThreadLocal的回收策略 通过阅读源码,我们可以很清楚的了解它的垃圾回收方式。下面看一下源码的doc说明文档 Each thread

那些你无意间踩过的坑-Java版

我的未来我决定 提交于 2019-12-03 02:04:47
1.ArrayList不是线程安全的,如果想要实现同步,可以使用:Collections.synchronizedList(List)将其包裹起来。 关于非安全的ArrayList与安全的实现可以参见:http://www.oschina.net/code/snippet_70229_2425 2.SimpleDateFormat也不是线程安全的,在多线程环境下,会出现问题,解决方法是使用ThreadLocal。即使将SimpleDateFormat设置为static,也不可避免,因为这根本是徒劳的。--官方推荐为每个线程创建一个实例,但显然这种方式比较浪费;但如果使用同步锁机制,又会带来性能问题。所以推荐使用ThreadLocal方式解决:一个线程里的变量是不存在多线程的。 使用ThreadLocal解决:(也可以使用 JODA日期时间处理库 / commons-lang 包中的 FastDateFormat 工具类来避免这些问题) private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; public static ThreadLocal local = new ThreadLocal<>(); protected synchronized Object initiaValue(){ return new

CookieManager for multiple threads

匿名 (未验证) 提交于 2019-12-03 01:07:01
可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试): 问题: I am trying to make multiple connections via threads. But every connection seems to override the other's cookies, resulting in the connections using the wrong cookies. inside the threaded class's constructor: manager = new CookieManager(); manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL); CookieHandler.setDefault(manager); Any way to manage the cookies per thread or per class? New failed try: Now every thread is using it's own index, yet they still seem to override each other cookie-wise. Any ideas? public class threadedCookieStore