http://116.85.35.192:8000/2018/04/threadlocal
首先,当前线程想要存放在ThreadLocal里面的数据,全部保存在了Thread的成员变量ThreadLocalMap里面,这当然是线程无关的。其次,当前线程想要获取值的时候,直接从Thread的成员变量ThreadLocalMap里面取出来即可。再者,如果当前线程需要存放多个数据,只需要构造出多个ThreadLocal对象,存到自己的ThreadLocalMap即可。
https://www.dynatrace.com/news/blog/the-top-java-memory-problems-part-1/
https://bz.apache.org/bugzilla/show_bug.cgi?id=50486
https://jira.qos.ch/browse/SLF4J-257
https://stackoverflow.com/questions/17968803/threadlocal-memory-leak/24862045#24862045
https://neilmadden.wordpress.com/2014/07/21/threadlocal-variables-and-permgen-memory-leaks-not-always-a-leak/
PermGen exhaustions in combination with
An example:
Imagine an application server which has a pool of worker threads.
They will be kept alive until application server termination.
A deployed web application uses a static
Important:
By definition, a reference to a
If the web application fails to clear the reference to the
Because the worker thread will usually never die and the reference to the
As a consequence, the web application's classloader cannot be garbage collected, which means that all classes (and all static data) of the web application remain loaded (this affects the PermGen memory pool as well as the heap).
Every redeployment iteration of the web application will increase permgen (and heap) usage.
Threads should never be killed, they should only be notified/interrupted in order to terminate gently by itself. Also, threads are expensive to create and often shared across multiple applications within the same container - but this is implementation-specific. However, some application servers drop all threads of a stopped web application (depending on the product/configuration), or renew its threads periodically in order to prevent such leaks.
https://stackoverflow.com/questions/3869026/how-to-clean-up-threadlocals
Use heap dump to detect thread local leaks.
https://www.pixelstech.net/article/1399361023-Use-Java-ThreadLocal-with-caution
https://wiki.apache.org/tomcat/MemoryLeakProtection
http://javarevisited.blogspot.com/2013/01/threadlocal-memory-leak-in-java-web.html
http://blog.xiaohansong.com/2016/08/06/ThreadLocal-memory-leak/
1.remove()调用expungeStaleEntry()全清,get()在miss的时候调用expungeStaleEntry()全清,而set调用的是cleanSomeSlots()随缘清理。
Source code:
Consider you have a Servlet which calls some business methods. You have a requirement to generate a unique transaction id for each and every request this servlet process and you need to pass this transaction id to the business methods, for logging purpose. One solution would be passing this transaction id as a parameter to all the business methods.
X.ThreadLocal - leak when app redeployment
https://plumbr.io/blog/locked-threads/how-to-shoot-yourself-in-foot-with-threadlocals
It is often the easiest way to render a stateful class thread-safe. And encapsulate non-thread-safe classes so that they can safely be used in multithreaded environments. In addition to simplicity, using ThreadLocal to store a per-thread-singleton or per-thread context information has a valuable information included – by using a ThreadLocal, it’s clear that the object stored in the ThreadLocal is not shared between threads, simplifying the task of determining whether a class is thread-safe or not. Which
ThreadLocal - Java Tutorial Blog
Following are the some of the different ways of implementing threadsafe operation:
On basic level ThreadLocal provides Thread Confinement which is extension of local variable. while local variable only accessible on block they are declared, ThreadLocal are visible only in Single Thread. No two Thread can see each others ThreadLocal variable.
We want to have separate instances(private copy) of a class so that there will not be any conflict among multiple threads. Each instance will be unique for each thread. This is nothing but a way of implementing threadsafety.
An important point about ThreadLocal variable is the global access. It can be accessed from anywhere inside the thread. Also note that, it is declared static and final.
http://veerasundar.com/blog/2010/11/java-thread-local-how-to-use-and-code-sample/
http://javarevisited.blogspot.com/2012/05/how-to-use-threadlocal-in-java-benefits.html
http://www.javamex.com/tutorials/synchronization_concurrency_thread_local2.shtml
XML parsers or other cases where creating an instance involves going through slightly non-trival code to 'choose a registered service provider';
Per-thread information such as profiling data which will be periodically collated.
Note that it is generally better not to re-use objects that are trivial to construct and finalize.
Example
using ThreadLocal to re-use Calendar objects
ThreadLocalRandom
It can be used to generate random numbers specific to parallel threads. Seed for random number will be unique for each thread.
ThreadLocalRandom.current().nextInt( 1, 3);
InheritableThreadLocal
The InheritableThreadLocal class is a subclass of ThreadLocal. Instead of each thread having its own value inside a ThreadLocal, the InheritableThreadLocal grants access to values to a thread and all child threads created by that thread.
http://www.appneta.com/blog/introduction-to-javas-threadlocal-storage/
ThreadLocal is implemented by having a Map (a ThreadLocalMap) as field (with WeakReference entry) within each Thread instance. (There are actually 2 maps; the second one is used for InheritabeleThreadLocal, but let’s not complicate the picture). The keys of those maps are the corresponding ThreadLocals themselves. Therefore, when a set/get is called on a ThreadLocal, it looks at the current thread, find the map, and look up the value with “this” ThreadLocal instance.
long running threads: servlets, thread pool.
How it's implemented?
http://www.javaspecialists.eu/archive/Issue229.html
http://howtodoinjava.com/2014/12/24/when-and-how-to-use-thread-local-variables/
When to use ThreadLocal?
For example, consider you are working on a eCommerce application. You have a requirement to generate a unique transaction id for each and every customer request this controller process and you need to pass this transaction id to the business methods in manager/DAO classes for logging purpose. One solution could be passing this transaction id as a parameter to all the business methods. But this is not a good solution as the code is redundant and unnecessary.
To solve that, here you can use
ThreadLocal来实现一个线程中的Connection是同一个,从而保证了事务
ThreadLocal提供一个线程(Thread)局部变量,访问到某个变量的每一个线程都拥有自己的局部变量。说白了,ThreadLocal就是想在多线程环境下去保证成员变量的安全
Read full article from ThreadLocal - Java Tutorial Blog
大致有两个思路。第一种,将这些线程和数据组成的关系对,存放在一个公共的区域,各个线程都可以自由获取,并且通过某些手段保证数据在线程之间互不影响。第二种,每个线程创建一个成员变量来保存这个关系对。
首先想到的HashMap
我们首先来看看第一种方式。
你一定知道HashMap,它对每一个键,都可以存储对应的一个值,并且根据不同的键,可以获取到对应的值。HashMap是不是符合我们的需求呢?
是的,看起来完全符合。但是,这里面有一点小小的区别。因为我们要区分的是不同的线程,而不是不同的键。那我把线程当成键不就行了?那么我们试试看。
一个新的问题
问题是,这样的话,我每一个线程只能存储一个数据(尽管这个数据是泛型)?如果我要存储多个数据是不是就没办法了?
按照目前的设计,似乎是这样的。那么我们可以改进吗?看起来没有办法。因为当前是把线程本身当做键,也就是说这个键对于每一个线程来说都是唯一的,那通过这个键获取的值,也就只能是一个。问题出现在这个键上面。
那我们是不是可以换一种方式,不要把线程当做键不就行了?事实上,不仅仅是线程本身不能作为键,所有能够唯一标志该线程的东西,都不能作为键。
如果不能使用标志线程的东西作为键,那我们能用什么呢?
首先,使用一个ThreadLocal存储线程的一个值是没问题的。但是,线程可能需要存储多个值。另外,一种想法是类似于HashMap存储多个Entry,我们使用ThreadLocalMap来存储多个Entry,把ThreadLocal作为Entry,但是ThreadLocalMap的键需要好好设计一下。
你肯定已经发现了,使用ThreadLocalMap这个想法其实包含了以下要求:
* 这个ThreadLocalMap不能放在公共的区域,因为放在公共的区域,每个线程去获取的话,只能通过标志线程的东西作为键,这个问题我们之前已经讨论过了。
* 这个ThreadLocalMap不能放在公共的区域,因为放在公共的区域,每个线程去获取的话,只能通过标志线程的东西作为键,这个问题我们之前已经讨论过了。
这样的话,我们只能把ThreadLocalMap当做线程(Thread)的一个成员变量,让线程自己持有这些数据关系。这其实也就是我们当初的第二种想法:
每个线程创建一个成员变量来保存这个关系对
ThreadLocalMap作为Thread的成员变量
终于,我们走到这条道路上面来了。实际上JDK里面的Thread类确实包含ThreadLocalMap成员变量,但是数量上不是一个,而是两个。你可以去看看源代码,然后想想为什么。
* ThreadLocal的get()方法是通过Thread.currentThread()作为键来获取值的。
* 不管在哪里的代码块,我们总是能够通过 Thread.currentThread()获取当前执行代码的线程。
* 每个线程都可以获取自己的成员变量——ThreadLocalMap。
* 不管在哪里的代码块,我们总是能够通过 Thread.currentThread()获取当前执行代码的线程。
* 每个线程都可以获取自己的成员变量——ThreadLocalMap。
这也就是说,即使是任何一个地方的ThreadLocal,我们也可以通过ThreadLocal.getMap()类似的方法来获取当前线程的ThreadLocalMap。
* ThreadLocal的get()方法是通过Thread.currentThread()作为键来获取值的。
* 不管在哪里的代码块,我们总是能够通过 Thread.currentThread()获取当前执行代码的线程。
* 每个线程都可以获取自己的成员变量——ThreadLocalMap。
* 不管在哪里的代码块,我们总是能够通过 Thread.currentThread()获取当前执行代码的线程。
* 每个线程都可以获取自己的成员变量——ThreadLocalMap。
这也就是说,即使是任何一个地方的ThreadLocal,我们也可以通过ThreadLocal.getMap()类似的方法来获取当前线程的ThreadLocalMap。
等等,好像有点不太对,我们一开始的ThreadLocal的get方法没有参数呀,我们想要的是把当前线程作为一种区分约束,直接获取线程独立的数据值。但是我们现在的get方法为何出现了Key这个参数?
看起来我们已经偏离需求了。那怎么办呢?按照需求来吧,先把参数Key去掉,然后我们再想办法解决其他问题。
现在的问题是,我们已经失去了Key这个参数,但是ThreadLocalMap又需要一个Key来获取对应的值。那该怎么办呢?这个Key总不能无中生有吧?
神奇的this
说到这里,你可能焕然大悟:ThreadLocalMap的键用ThreadLocal不就行了!!!
https://www.dynatrace.com/news/blog/the-top-java-memory-problems-part-1/
https://bz.apache.org/bugzilla/show_bug.cgi?id=50486
https://jira.qos.ch/browse/SLF4J-257
https://stackoverflow.com/questions/17968803/threadlocal-memory-leak/24862045#24862045
https://neilmadden.wordpress.com/2014/07/21/threadlocal-variables-and-permgen-memory-leaks-not-always-a-leak/
PermGen exhaustions in combination with
ThreadLocal
are often caused by classloader leaks.An example:
Imagine an application server which has a pool of worker threads.
They will be kept alive until application server termination.
A deployed web application uses a static
ThreadLocal
in one of its classes in order to store some thread-local data, an instance of another class (lets call it SomeClass
) of the web application. This is done within the worker thread (e.g. this action originates from a HTTP request).Important:
By definition, a reference to a
ThreadLocal
value is kept until the "owning" thread dies or if the ThreadLocal itself is no longer reachable.If the web application fails to clear the reference to the
ThreadLocal
on shutdown, bad things will happen:Because the worker thread will usually never die and the reference to the
ThreadLocal
is static, the ThreadLocal
value still references the instance of SomeClass
, a web application's class - even if the web application has been stopped!As a consequence, the web application's classloader cannot be garbage collected, which means that all classes (and all static data) of the web application remain loaded (this affects the PermGen memory pool as well as the heap).
Every redeployment iteration of the web application will increase permgen (and heap) usage.
Threads should never be killed, they should only be notified/interrupted in order to terminate gently by itself. Also, threads are expensive to create and often shared across multiple applications within the same container - but this is implementation-specific. However, some application servers drop all threads of a stopped web application (depending on the product/configuration), or renew its threads periodically in order to prevent such leaks.
In this case the only references to the ThreadLocal are in the static final field of a class that has now become a target for GC, and the reference from the worker threads. However, the references from the worker threads to the ThreadLocal are WeakReferences!
The values of a ThreadLocal are not weak references, however. So, if you have references in the values of a ThreadLocal to application classes, then these will maintain a reference to the ClassLoader and prevent GC. However, if your ThreadLocal values are just integers or strings or some other basic object type (e.g., a standard collection of the above), then there should not be a problem (they will only prevent GC of the boot/system classloader, which is never going to happen anyway).
It is still good practice to explicitly clean up a ThreadLocal when you are done with it, but in the case of the cited log4j bug the sky was definitely not falling
When we run this, we can see that the CustomClassLoader is indeed not garbage collected (as the thread local in the main thread has a reference to a Foo instance that was loaded by our custom classloader):
However, when we change the ThreadLocal to instead contain a reference to a simple Integer rather than a Foo instance:
Then we see that the custom classloader is now garbage collected (as the thread local on the main thread only has a reference to an integer loaded by the system classloader):
if you make the mistake of creating a new
ThreadLocal
instances over and over again (instead of using a static
variable to hold a singleton instance), the thread local values won't get overwritten, and will accumulate in each thread's threadlocals
map. This could result in a serious leak.
Assuming that you are talking about thread locals that are created / used during a webapp's processing of an HTTP request, then one way to avoid the thread local leaks is to register a
ServletRequestListener
with your webapp's ServletContext
and implement the listener's requestDestroyed
method to cleanup the thread locals for the current thread.Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()
https://blog.codecentric.de/en/2008/09/a-threadlocal-memory-leak/Use heap dump to detect thread local leaks.
https://www.pixelstech.net/article/1399361023-Use-Java-ThreadLocal-with-caution
One common use of ThreadLocal is when you want to access some non thread-safe objects in threads without using synchronization mechanisms like synchronized block and locks. These variables will not share states among different threads, so there is no synchronization problem; while at the same since each thread will have only one instance of the ThreadLocal object, it saves memory.
public class ThreadId { // Atomic integer containing the next thread ID to be assigned private static final AtomicInteger nextId = new AtomicInteger( 0 ); // Thread local variable containing each thread's ID private static final ThreadLocal threadId = new ThreadLocal() { @Override protected Integer initialValue() { return nextId.getAndIncrement(); } }; // Returns the current thread's unique ID, assigning it if necessary public static int get() { return threadId.get(); } }
If you do not clean up when you're done, any references it holds to classes loaded as part of a deployed webapp will remain in the permanent heap and will never get garbage collected. Redeploying/undeploying the webapp will not clean up each
You will end up with out of memory exceptions due to
|
https://wiki.apache.org/tomcat/MemoryLeakProtection
Starting with tomcat 6.0.25, the manager webapp has a new "Find Leaks" button. When triggered, it displays a list of webapps (their context path) that have been stopped (this includes undeployed and redeployed ones) but whose classloader failed to be GCed.
TODO https://particular.net/blog/the-dangers-of-threadlocalhttp://javarevisited.blogspot.com/2013/01/threadlocal-memory-leak-in-java-web.html
Many people use Filters to initialize and remove ThreadLocal variables. You can initialize ThreadLocal in filter, put some expensive object as ThreadLocal and once request has been processed remove it from ThreadLocal as shown in below example:
public void doFilter(ServeletRequest request, ServletResponse){
try{
//set ThreadLocal variable
chain.doFilter(request, response)
}finally{
//remove threadLocal variable.
}
}
try{
//set ThreadLocal variable
chain.doFilter(request, response)
}finally{
//remove threadLocal variable.
}
}
http://blog.xiaohansong.com/2016/08/06/ThreadLocal-memory-leak/
ThreadLocal
的实现是这样的:每个Thread
维护一个 ThreadLocalMap
映射表,这个映射表的 key
是 ThreadLocal
实例本身,value
是真正需要存储的 Object
。
也就是说
ThreadLocal
本身并不存储值,它只是作为一个 key
来让线程从 ThreadLocalMap
获取 value
。值得注意的是图中的虚线,表示 ThreadLocalMap
是使用 ThreadLocal
的弱引用作为 Key
的,弱引用的对象在 GC 时会被回收。ThreadLocalMap
使用ThreadLocal
的弱引用作为key
,如果一个ThreadLocal
没有外部强引用来引用它,那么系统 GC 的时候,这个ThreadLocal
势必会被回收,这样一来,ThreadLocalMap
中就会出现key
为null
的Entry
,就没有办法访问这些key
为null
的Entry
的value
,如果当前线程再迟迟不结束的话,这些key
为null
的Entry
的value
就会一直存在一条强引用链:Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value
永远无法回收,造成内存泄漏。
其实,
ThreadLocalMap
的设计中已经考虑到这种情况,也加上了一些防护措施:在ThreadLocal
的get()
,set()
,remove()
的时候都会清除线程ThreadLocalMap
里所有key
为null
的value
。
但是这些被动的预防措施并不能保证不会内存泄漏:
- 使用
static
的ThreadLocal
,延长了ThreadLocal
的生命周期,可能导致的内存泄漏(参考ThreadLocal 内存泄露的实例分析)。 - 分配使用了
ThreadLocal
又不再调用get()
,set()
,remove()
方法,那么就会导致内存泄漏。
To help deal with very large and long-lived usages, the hash table entries use WeakReferences for keys.
为了应对非常大和长时间的用途,哈希表使用弱引用的 key。
下面我们分两种情况讨论:
- key 使用强引用:引用的
ThreadLocal
的对象被回收了,但是ThreadLocalMap
还持有ThreadLocal
的强引用,如果没有手动删除,ThreadLocal
不会被回收,导致Entry
内存泄漏。 - key 使用弱引用:引用的
ThreadLocal
的对象被回收了,由于ThreadLocalMap
持有ThreadLocal
的弱引用,即使没有手动删除,ThreadLocal
也会被回收。value
在下一次ThreadLocalMap
调用set
,get
,remove
的时候会被清除。
比较两种情况,我们可以发现:由于
ThreadLocalMap
的生命周期跟Thread
一样长,如果都没有手动删除对应key
,都会导致内存泄漏,但是使用弱引用可以多一层保障:弱引用ThreadLocal
不会内存泄漏,对应的value
在下一次ThreadLocalMap
调用set
,get
,remove
的时候会被清除。
因此,
ThreadLocal
内存泄漏的根源是:由于ThreadLocalMap
的生命周期跟Thread
一样长,如果没有手动删除对应key
就会导致内存泄漏,而不是因为弱引用。
综合上面的分析,我们可以理解
ThreadLocal
内存泄漏的前因后果,那么怎么避免内存泄漏呢?- 每次使用完
ThreadLocal
,都调用它的remove()
方法,清除数据。
在使用线程池的情况下,没有及时清理
ThreadLocal
,不仅是内存泄漏的问题,更严重的是可能导致业务逻辑出现问题。所以,使用ThreadLocal
就跟加锁完要解锁一样,用完就清理。
在 Tomcat 中,下面的代码都在 webapp 内,会导致
WebappClassLoader
泄漏,无法被回收。public class MyCounter { private int count = 0; public void increment() { count++; } public int getCount() { return count; } } public class MyThreadLocal extends ThreadLocal<MyCounter> { } public class LeakingServlet extends HttpServlet { private
static
MyThreadLocal myThreadLocal = new MyThreadLocal(); protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { MyCounter counter = myThreadLocal.get(); if (counter == null) { counter = new MyCounter(); myThreadLocal.set(counter); } response.getWriter().println( "The current thread served this servlet " + counter.getCount() + " times"); counter.increment(); } }
上面的代码中,只要
LeakingServlet
被调用过一次,且执行它的线程没有停止,就会导致WebappClassLoader
泄漏。每次你 reload 一下应用,就会多一份WebappClassLoader
实例,最后导致 PermGen OutOfMemoryException
。
类加载器对象跟它加载的 Class 对象是双向关联的。这意味着,Class 对象可能就是强引用
WebappClassLoader
,导致它泄漏的元凶。
内存泄漏是很难发现的问题,往往由于多方面原因造成。
ThreadLocal
由于它与线程绑定的生命周期成为了内存泄漏的常客,稍有不慎就酿成大祸。
Normally, as the thread dies on end of execution, the objects stored in ThreadLocals are no longer referenced and the garbage collector takes care of removing such objects:
Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the ThreadLocal instance is accessible; after a thread goes away, all of its copies of thread-local instances are subject to garbage collection (unless other references to these copies exist).
But when the thread has been fetched from a thread pool, it does not die, but instead is returned to the pool. Since the thread is still alive, so are the referenced ThreadLocals. This manifests both as memory leaks and "leaking" of values from one request to another when the same ThreadLocal is used and the thread handling the request/task was used before.
每个thread中都存在一个map, map的类型是ThreadLocal.ThreadLocalMap. Map中的key为一个threadlocal实例. 这个Map的确使用了弱引用,不过弱引用只是针对key. 每个key都弱引用指向threadlocal. 当把threadlocal实例置为null以后,没有任何强引用指向threadlocal实例,所以threadlocal将会被gc回收. 但是,我们的value却不能回收,因为存在一条从current thread连接过来的强引用. 只有当前thread结束以后, current thread就不会存在栈中,强引用断开, Current Thread, Map, value将全部被GC回收.
所以得出一个结论就是只要这个线程对象被gc回收,就不会出现内存泄露,但在threadLocal设为null和线程结束这段时间不会被回收的,就发生了我们认为的内存泄露。其实这是一个对概念理解的不一致,也没什么好争论的。最要命的是线程对象不被回收的情况,这就发生了真正意义上的内存泄露。比如使用线程池的时候,线程结束是不会销毁的,会再次使用的。就可能出现内存泄露。
PS.Java为了最小化减少内存泄露的可能性和影响,在ThreadLocal的get,set的时候都会清除线程Map里所有key为null的value。所以最怕的情况就是,threadLocal对象设null了,开始发生“内存泄露”,然后使用线程池,这个线程结束,线程放回线程池中不销毁,这个线程一直不被使用,或者分配使用了又不再调用get,set方法,那么这个期间就会发生真正的内存泄露。
Source code:
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
你会看到,set需要首先获得当前线程对象Thread;
然后取出当前线程对象的成员变量ThreadLocalMap;
如果ThreadLocalMap存在,那么进行KEY/VALUE设置,KEY就是ThreadLocal;
如果ThreadLocalMap没有,那么创建一个;
说白了,当前线程中存在一个Map变量,KEY是ThreadLocal,VALUE是你设置的值。
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
private T setInitialValue() {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
这里其实揭示了ThreadLocalMap里面的数据存储结构,从上面的代码来看,ThreadLocalMap中存放的就是Entry,Entry的KEY就是ThreadLocal,VALUE就是值
这里我们思考一个问题:ThreadLocal使用到了弱引用,是否意味着不会存在内存泄露呢?
首先来说,如果把ThreadLocal置为null,那么意味着Heap中的ThreadLocal实例不在有强引用指向,只有弱引用存在,因此GC是可以回收这部分空间的,也就是key是可以回收的。但是value却存在一条从Current Thread过来的强引用链。因此只有当Current Thread销毁时,value才能得到释放。
因此,只要这个线程对象被gc回收,就不会出现内存泄露,但在threadLocal设为null和线程结束这段时间内不会被回收的,就发生了我们认为的内存泄露。最要命的是线程对象不被回收的情况,比如使用线程池的时候,线程结束是不会销毁的,再次使用的,就可能出现内存泄露。
那么如何有效的避免呢?
事实上,在ThreadLocalMap中的set/getEntry方法中,会对key为null(也即是ThreadLocal为null)进行判断,如果为null的话,那么是会对value置为null的。我们也可以通过调用ThreadLocal的remove方法进行释放!
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
private Entry[] table;
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
table = new Entry[INITIAL_CAPACITY];
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
table[i] = new Entry(firstKey, firstValue);
size = 1;
setThreshold(INITIAL_CAPACITY);
}
private void set(ThreadLocal<?> key, Object value) {
// We don't use a fast path as with get() because it is at
// least as common to use set() to create new entries as
// it is to replace existing ones, in which case, a fast
// path would fail more often than not.
Entry[] tab = table;
int len = tab.length;
int i = key.threadLocalHashCode & (len-1);
for (Entry e = tab[i];
e != null;
e = tab[i = nextIndex(i, len)]) {
ThreadLocal<?> k = e.get();
if (k == key) {
e.value = value;
return;
}
if (k == null) {
replaceStaleEntry(key, value, i);
return;
}
}
tab[i] = new Entry(key, value);
int sz = ++size;
if (!cleanSomeSlots(i, sz) && sz >= threshold)
rehash();
}
private static int nextIndex(int i, int len) {
return ((i + 1 < len) ? i + 1 : 0);
}
private static int prevIndex(int i, int len) {
return ((i - 1 >= 0) ? i - 1 : len - 1);
}
private Entry getEntry(ThreadLocal<?> key) {
int i = key.threadLocalHashCode & (table.length - 1);
Entry e = table[i];
if (e != null && e.get() == key)
return e;
else
return getEntryAfterMiss(key, i, e);
}
private Entry getEntryAfterMiss(ThreadLocal<?> key, int i, Entry e) {
Entry[] tab = table;
int len = tab.length;
while (e != null) {
ThreadLocal<?> k = e.get();
if (k == key)
return e;
if (k == null)
expungeStaleEntry(i);
else
i = nextIndex(i, len);
e = tab[i];
}
return null;
}
https://veerasundar.com/blog/2010/11/java-thread-local-how-to-use-and-code-sample/Consider you have a Servlet which calls some business methods. You have a requirement to generate a unique transaction id for each and every request this servlet process and you need to pass this transaction id to the business methods, for logging purpose. One solution would be passing this transaction id as a parameter to all the business methods.
X.ThreadLocal - leak when app redeployment
https://plumbr.io/blog/locked-threads/how-to-shoot-yourself-in-foot-with-threadlocals
It is often the easiest way to render a stateful class thread-safe. And encapsulate non-thread-safe classes so that they can safely be used in multithreaded environments. In addition to simplicity, using ThreadLocal to store a per-thread-singleton or per-thread context information has a valuable information included – by using a ThreadLocal, it’s clear that the object stored in the ThreadLocal is not shared between threads, simplifying the task of determining whether a class is thread-safe or not. Which
- ThreadLocal gives you the opportunity to use the variables without explicitly passing them down through the method invocation chain. Which could be useful on certain occasions. But you guys out there who have created a n-layer architecture to abstract away different communication interfaces. And then grab HttpServletRequest from ThreadLocals in your DAO objects … what were you smoking when making this decision? It took a few hours and a second pair of eyes when we were digging up this particular case. But anyhow – be careful when using the powers of globalization. You end up creating unexpected dependencies within your code. And as you might remember – this is not a wise thing to do.
- It is darn easy to introduce a memory leak to your code when using a ThreadLocal. Which serves as a nice demonstration about the complexities surrounding classloaders. If you are deploying your code in an application server then your application classes are loaded/unloaded with a different classloader than the one used by the application server itself. Which is not bad per se. But now considering that modern application servers also pool threads instead of creating a new one on each HttpRequest, we have built the foundation to a problem.
If one of the application classes stores a value in ThreadLocal variable and doesn’t remove it after the task at hand is completed, a copy of that Object will remain with the Thread (from the application server thread pool). Since lifespan of the pooled Thread surpasses that of the application, it will prevent the object and thus a ClassLoader being responsible for loading the application from being garbage collected. And we have created a leak, which has a chance to surface in a good old java.lang.OutOfMemoryError: PermGen space form.
ThreadLocal in Java is a mechanism to provide separate copy of shared object to every Thread. So that they no longer shared between multiple Threads and remain thread-safe. ThreadLocal variables are stored in a special map called ThreadLocalMap which is designed to hold thread local objects, it uses WeakReferences for keys.
Since every Thread has strong reference to there copy of ThreadLocal variables, they are not garbage collected until Thread is Alive and this is what creates memory leak in a typical J2EE web application
Since every Thread has strong reference to there copy of ThreadLocal variables, they are not garbage collected until Thread is Alive and this is what creates memory leak in a typical J2EE web application
In web server and application server like Tomcat or WebLogic, web-app is loaded by a different ClassLoader than which is used by Server itself. This ClassLoader loads and unloads classes from web application. Web servers also maintains ThreadPool, which is collection of worker thread, to server HTTP requests. Now if one of the Servlet or any other Java class from web application creates a ThreadLocal variable during requestprocessing and doesn't remove it after that, copy of that Object will remain with worker Thread and since life-span of worker Thread is more than web app itself, it will prevent the object and ClassLoader, which uploaded the web app, from being garbage collected. This will create a memory leak in Server. Now if you do this couple of time you may see java.lang.OutOfMemoryError: PermGen space . Now this brings an important question, is it possible to to use ThreadLocal variable safely in a managed environment? Answer is Yes,, but that requires a careful usage of ThreadLocal variable and making sure to remove the object from ThreadLocal once done.
How to use ThreadLocal safely in Java Web application
Many people use Filters to initialize and remove ThreadLocal variables. You can initialize ThreadLocal in filter, put some expensive object as ThreadLocal and once request has been processed remove it from ThreadLocal as shown in below example:
public void doFilter(ServeletRequest request, ServletResponse){
try{
//set ThreadLocal variable
chain.doFilter(request, response)
}finally{
//remove threadLocal variable.
}
}
try{
//set ThreadLocal variable
chain.doFilter(request, response)
}finally{
//remove threadLocal variable.
}
}
Following are the some of the different ways of implementing threadsafe operation:
- Re-entrancy
- Mutual exclusion (synchronization)
- Thread-local
- Atomic operation
On basic level ThreadLocal provides Thread Confinement which is extension of local variable. while local variable only accessible on block they are declared, ThreadLocal are visible only in Single Thread. No two Thread can see each others ThreadLocal variable.
We want to have separate instances(private copy) of a class so that there will not be any conflict among multiple threads. Each instance will be unique for each thread. This is nothing but a way of implementing threadsafety.
An important point about ThreadLocal variable is the global access. It can be accessed from anywhere inside the thread. Also note that, it is declared static and final.
http://veerasundar.com/blog/2010/11/java-thread-local-how-to-use-and-code-sample/
Thread Local can be considered as a scope of access, like a request scope or session scope. It’s athread scope. You can set any object in Thread Local and this object will be global and local to the specific thread which is accessing this object.
- Values stored in Thread Local are global to the thread, meaning that they can be accessed from anywhere inside that thread. If a thread calls methods from several classes, then all the methods can see the Thread Local variable set by other methods (because they are executing in same thread). The value need not be passed explicitly. It’s like how you use global variables.
- Values stored in Thread Local are local to the thread, meaning that each thread will have it’s own Thread Local variable. One thread can not access/modify other thread’s Thread Local variables.
http://javarevisited.blogspot.com/2012/05/how-to-use-threadlocal-in-java-benefits.html
1) ThreadLocal are fantastic to implement Per Thread Singleton classes or per thread context information like transaction id.
2) You can wrap any non Thread Safe object in ThreadLocal and suddenly its uses becomes Thread-safe, as its only being used by Thread Safe. One of the classic example of ThreadLocal is sharing SimpleDateForamt. SinceSimpleDateFormat is not thread safe, having a global formatter may not work but having per Thread formatter will certainly work.
3) ThreadLocal provides another way to extend Thread. If you want to preserve or carry information from one method call to another you can carry it by using ThreadLocal. This can provide immense flexibility as you don't need to modify any method.
3. Each thread holds an exclusive copy of ThreadLocal variable which becomes eligible to Garbage collection after thread finished or died, normally or due to any Exception, Given those ThreadLocal variable doesn't have any other live references.
4. ThreadLocal variables in Java are generally private static fields in Classes and maintain its state inside Thread.
When to Use?http://www.javamex.com/tutorials/synchronization_concurrency_thread_local2.shtml
A typical example of using ThreadLocal would be as an alternative to an object or resource pool, when we don't mind creating one object per thread. Let's consider the example of a pool of Calendar instances. In an application that does a lot of date manipulation, Calendar classes may be a good candidates for pooling because:
- Creating a Calendar is non-trivial (various calculations and accesses to localisation resources need to be made each time one is created);
- There's no actual requirement to share Calendars between threads or have fewer calendars than threads.
Consider you have a Servlet which calls some business methods. You have a requirement to generate a unique transaction id for each and every request this servlet process and you need to pass this transaction id to the business methods, for logging purpose. One solution would be passing this transaction id as a parameter to all the business methods. But this is not a good solution as the code is redundant and unnecessary.
To solve that, you can use Thread Local. You can generate a transaction id (either in servlet or better in a filter) and set it in the Thread Local. After this, what ever the business method, that this servlet calls, can access the transaction id from the thread local.
When to use ThreadLocal?- The objects are non-trivial to construct;
- An instance of the object is frequently needed by a given thread;
- The application pools threads, such as in a typical server (if every time the thread-local is used it is from a new thread, then a new object will still be created on each call!);
- It doesn't matter that Thread A will never share an instance with Thread B;
XML parsers or other cases where creating an instance involves going through slightly non-trival code to 'choose a registered service provider';
Per-thread information such as profiling data which will be periodically collated.
Note that it is generally better not to re-use objects that are trivial to construct and finalize.
Example
using ThreadLocal to re-use Calendar objects
public class CalendarFactory { private ThreadLocal<Calendar> calendarRef = new ThreadLocal<Calendar>() { protected Calendar initialValue() { return new GregorianCalendar(); } }; private static CalendarFactory instance = new CalendarFactory(); public static CalendarFactory getFactory() { return instance; } public Calendar getCalendar() { return calendarRef.get(); } // Don't let outsiders create new factories directly private CalendarFactory() {} }
public class ThreadLocalExample { private static final ThreadLocal formatter = new ThreadLocal() { protected SimpleDateFormat initialValue() { return new SimpleDateFormat("yyyyMMdd HHmm"); } }; public String formatIt(Date date) { return formatter.get().format(date); } }
public
class
TransactionManager {
private
static
final
ThreadLocal<String> context =
new
ThreadLocal<String>();
public
static
void
startTransaction() {
//logic to start a transaction
//...
context.set(generatedId);
}
public
static
String getTransactionId() {
return
context.get();
}
public
static
void
endTransaction() {
//logic to end a transaction
//…
context.remove();
}
}
ThreadLocalRandom
It can be used to generate random numbers specific to parallel threads. Seed for random number will be unique for each thread.
ThreadLocalRandom.current().nextInt( 1, 3);
InheritableThreadLocal
The InheritableThreadLocal class is a subclass of ThreadLocal. Instead of each thread having its own value inside a ThreadLocal, the InheritableThreadLocal grants access to values to a thread and all child threads created by that thread.
http://www.appneta.com/blog/introduction-to-javas-threadlocal-storage/
ThreadLocal is implemented by having a Map (a ThreadLocalMap) as field (with WeakReference entry) within each Thread instance. (There are actually 2 maps; the second one is used for InheritabeleThreadLocal, but let’s not complicate the picture). The keys of those maps are the corresponding ThreadLocals themselves. Therefore, when a set/get is called on a ThreadLocal, it looks at the current thread, find the map, and look up the value with “this” ThreadLocal instance.
Still confused? I certainly am. Let’s look at a real example.
- Code running in Thread 1 calls set() on ThreadLocal instance “A” with value “123″
- Code running in Thread 2 calls set() on ThreadLocal instance “A” with value “234″
- Code running in Thread 1 calls set() on ThreadLocal instance “B” with value “345″
And this is the end result:
Thread 1 (the instance)’s field ThreadLocalMap (m1) has 2 entries:
Key | Value |
---|---|
ThreadLocal A | “123″ |
ThreadLocal B | “345″ |
Thread 2 (the instance)’s field ThreadLocalMap (m2) has 1 entry:
Key | Value |
---|---|
ThreadLocal A | “234″ |
Now if some code logic in Thread 1 calls get() on ThreadLocal instance “A”, the ThreadLocal logic will lookup the current Thread, which is instance Thread 1, then access the field ThreadLocalMap of that Thread instance, which is m1, it can then lookup the value by using m1.get(this), with “this” as ThreadLocal and the result is “123″
Always clean up/reset your threadlocal after you have finished your “unit of operation”! Even though the current code might be simple enough to bypass the cleanups, it might be adapted and integrated into servlets/thread pooling later on!
long running threads: servlets, thread pool.
How it's implemented?
public class ThreadLocal<T> {
private final int threadLocalHashCode = nextHashCode();
* The next hash code to be given out. Updated atomically. Starts at
* zero.
*/
private static AtomicInteger nextHashCode =
new AtomicInteger();
Returns the value in the current thread's copy of this thread-local variable. If the variable has no value for the current thread, it is first initialized to the value returned by an invocation of the initialValue method.
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
private T setInitialValue() {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}
* Get the map associated with a ThreadLocal. Overridden in
* InheritableThreadLocal.
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
ThreadLocalMap is a customized hash map suitable only for maintaining thread local values. No operations are exported outside of the ThreadLocal class. The class is package private to allow declaration of fields in class Thread. To help deal with very large and long-lived usages, the hash table entries use WeakReferences for keys. However, since reference queues are not used, stale entries are guaranteed to be removed only when the table starts running out of space.
static class {
* The entries in this hash map extend WeakReference, using
* its main ref field as the key (which is always a
* ThreadLocal object). Note that null keys (i.e. entry.get()
* == null) mean that the key is no longer referenced, so the
* entry can be expunged from table. Such entries are referred to
* as "stale entries" in the code that follows.
*/
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
private Entry[] table;
}
class Thread implements Runnable
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
/*
* InheritableThreadLocal values pertaining to this thread. This map is
* maintained by the InheritableThreadLocal class.
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
http://www.javaspecialists.eu/archive/Issue229.html
http://howtodoinjava.com/2014/12/24/when-and-how-to-use-thread-local-variables/
When to use ThreadLocal?
For example, consider you are working on a eCommerce application. You have a requirement to generate a unique transaction id for each and every customer request this controller process and you need to pass this transaction id to the business methods in manager/DAO classes for logging purpose. One solution could be passing this transaction id as a parameter to all the business methods. But this is not a good solution as the code is redundant and unnecessary.
To solve that, here you can use
ThreadLocal
variable. You can generate a transaction id in controller OR any pre-processor interceptor; and set this transaction id in the ThreadLocal
. After this, whatever the methods, that this controller calls, they all can access this transaction id from the threadlocal.class
DemoTask
implements
Runnable {
// Atomic integer containing the next thread ID to be assigned
private
static
final
AtomicInteger nextId =
new
AtomicInteger(
0
);
// Thread local variable containing each thread's ID
private
static
final
ThreadLocal<Integer> threadId =
new
ThreadLocal<Integer>() {
@Override
protected
Integer initialValue() {
return
nextId.getAndIncrement();
}
};
// Returns the current thread's unique ID, assigning it if necessary
public
int
getThreadId() {
return
threadId.get();
}
// Returns the current thread's starting timestamp
private
static
final
ThreadLocal<Date> startDate =
new
ThreadLocal<Date>() {
protected
Date initialValue() {
return
new
Date();
}
};
}
In wabapp server, it may be keep a thread pool, so a ThreadLocal var should be removed before response to the client, since current thread may be reused by next request. Also, if you do not clean up when you’re done, any references it holds to classes loaded as part of a deployed webapp will remain in the permanent heap and will never get garbage collected.
https://www.jianshu.com/p/ee8c9dccc953ThreadLocal来实现一个线程中的Connection是同一个,从而保证了事务
ThreadLocal提供一个线程(Thread)局部变量,访问到某个变量的每一个线程都拥有自己的局部变量。说白了,ThreadLocal就是想在多线程环境下去保证成员变量的安全
虽然,ThreadLocal让访问某个变量的线程都拥有自己的局部变量,但是如果这个局部变量都指向同一个对象呢?这个时候ThreadLocal就失效了。仔细观察下图中的代码,你会发现,threadLocal在初始化时返回的都是同一个对象a!
Read full article from ThreadLocal - Java Tutorial Blog