待整理 ThreadLocal

ThreadLocal 可以理解成 Current Thread Context 或 Current Thread Local Variable。

[b][url]http://www.appneta.com/blog/introduction-to-javas-threadlocal-storage/[/url][/b]
[url]http://javarevisited.blogspot.com/2012/05/how-to-use-threadlocal-in-java-benefits.html[/url][quote]ThreadLocal in Java is another way to achieve [b]thread-safety[/b] apart from writing immutable classes. If you have been writing multi-threaded or concurrent code in Java then you must be familiar with cost of synchronization or locking which can greatly affect Scalability of application, but there is no choice other than synchronize if you are [b]sharing[/b] objects between multiple threads. ThreadLocal in Java is a different way to achieve thread-safety, it doesn't address synchronization requirement, instead [b]it [color=red]eliminates sharing[/color] by providing explicitly copy of Object to each thread.[/b] Since Object is no more shared there is no requirement of Synchronization which can improve scalability and performance of application.[/quote]

When and how should I use a ThreadLocal variable?
[url]http://stackoverflow.com/questions/817856/when-and-how-should-i-use-a-threadlocal-variable[/url][quote]Since a ThreadLocal is a reference to data within a given Thread, you can end up with classloading leaks when using ThreadLocals in application servers which use thread pools. You need to be very careful about cleaning up any ThreadLocals you get() or set() by using the ThreadLocal's remove() method.

Many frameworks use ThreadLocals to maintain some context related to the current thread. For example when the current transaction is stored in a ThreadLocal, you don't need to pass it as a parameter through every method call, in case someone down the stack needs access to it. Web applications might store information about the current request and session in a ThreadLocal, so that the application has easy access to them. With Guice you can use ThreadLocals when implementing custom scopes for the injected objects (Guice's default servlet scopes most probably use them as well).
ThreadLocals are one sort of global variables (although slightly less evil because they are restricted to one thread), so you should be careful when using them to avoid unwanted side-effects and memory leaks. Design your APIs so that the ThreadLocal values will always be automatically cleared when they are not anymore needed and that incorrect use of the API won't be possible (for example like this). ThreadLocals can be used to make the code cleaner, and in some rare cases they are the only way to make something work (my current project had two such cases; they are documented here under "Static Fields and Global Variables").[/quote]


Why is java.lang.ThreadLocal a map on Thread instead on the ThreadLocal?
[url]http://stackoverflow.com/questions/1829046/why-is-java-lang-threadlocal-a-map-on-thread-instead-on-the-threadlocal?rq=1[/url]


[color=red][b]ThreadLocal + Thread pool:[/b][/color] (thread pool 参见:[url]http://wuaner.iteye.com/blog/1709915[/url])
同时使用 ThreadLocal 和 Thread pool 不是一个好的设计方案![b]不要试图用 InheritableThreadLocal 向 reused ThreadPool 中 传递 threadlocal vars![/b]In most containers, threads are reused via thread pools and thus are never gc. this would lead something wired。
[b]原因:[/b]
[url]http://www2.sys-con.com/itsg/virtualcd/java/archives/0711/goenka/index.html[/url][quote]Thread Pooling Breaks Usage of Thread-Local Variables
Thread pooling is not friendly to the java.lang.ThreadLocal and java.lang.InheritableThreadLocal classes that were introduced in JDK 1.2 to provide thread-local variables. These variables differ from other variables in that each thread has its own independently initialized copy of the variable. The typical usage of a thread-local variable in a multithreaded application is to keep track of some application context associated with the request, such as the identity of the user making the request. The get() and set() methods in the ThreadLocal class return and set the value that corresponds to the executing thread. Thus, each thread executing a get() on a given ThreadLocal variable can potentially get a different object. The set() similarly allows each executing thread to set a different value for the same ThreadLocal variable.[/quote][url]http://www.cxyclub.cn/n/28026/[/url]
[url]http://stackoverflow.com/questions/7403809/java-cached-thread-pool-and-thread-local[/url]
[url]http://stackoverflow.com/questions/9012371/using-inheritablethreadlocal-with-threadpoolexecutor-or-a-threadpoolexecut?lq=1[/url]
[b]避免问题的方法:[/b]
1 不要重用 Thread pool 中的线程,每次都建立新的(即,不要将 Thread poll,如 ExecutorService 设为成员变量,而作为 局部变量 使用):
[url]http://stackoverflow.com/questions/18129039/thread-pooling-and-inheritedthreadlocal[/url]
我们使用 Thread pool 的原因就是为了重用线程池中线程,以达到最小的线程创建/销毁的开销;所以,尽管这种方式可以避免 ThreadLocal + Thread pool 的问题,但不是一个好的解决办法。



同样的道理,在tomcat 等web container 中,为了性能的需要,也存在 request thread pool(如 tomcat 默认的大小为 200);既然存在 thread reuse,那当在这些web container中使用 ThreadLocal 时也会存在上面的问题。解决办法:
1 使用 servlet Filter 在每次访问请求前清理当前 thread 中的threadlocal:
[url]http://luchinkup.blogspot.com/2005/06/threadlocal-rocks-and-dont-let-em-tell.html[/url]


[b]ThreadLocal 与 内存泄露:[/b]
[url]http://dave.srednal.com/archives/14[/url]


[b]ThreadLocal 的 remove() 和 set(null) 的区别是什么?[/b]
[url]http://stackoverflow.com/questions/12424838/threadlocal-remove[/url]


对非线程安全的对象如 SimpleDateFormat,使用 ThreadLocal 来确保线程安全是个不错的选择:
[url]http://stackoverflow.com/questions/4107839/synchronizing-access-to-simpledateformat[/url][quote]三种方式确保 的线程安全:
Option 1: Create local instances when required
Option 2: Create an instance of SimpleDateFormat as a class variable but synchronize access to it.
Option 3: Create a ThreadLocal to store a different instance of SimpleDateFormat for each thread.
各自的好坏:
1. Creating SimpleDateFormat is expensive. Don't use this unless it's done seldom.
2. OK if you can live with a bit of blocking. Use if formatDate() is not used much.
3. Fastest option IF you reuse threads (thread pool). Uses more memory than 2. and has higher startup overhead.

For applications both 2. and 3. are viable options. Which is best for your case depends on your use case. Beware of premature optimization. Only do it if you believe this is an issue.

For libraries that would be used by 3rd party I'd use option 3.[/quote]


[b]ThreadLocal explained:[/b]
[url]http://doanduyhai.wordpress.com/2011/12/04/threadlocal-explained/[/url][quote]A ThreadLocal object is created, then attached to the current thread. All portion of your program executed by the current thread can access the ThreadLocal target Object, provided that the code can access the ThreadLocal reference, and that’s the trick! There is no point creating a ThreadLocal if it cannot be accessed everywhere in your code.
Most of the time, the ThreadLocal object itself is created as a static final variable. Static to make it accessible from everywhere and final to avoid being modified. There is no need to synchronize the access to the ThreadLocal object itself since only the target Object is usefull and this object is different from one thread to another (so thread-safe by nature)

public class ThreadLocalTest implements Runnable {

private static final ThreadLocal<String> threadLocal = new ThreadLocal<String>();

private String value;
private long delayTime;
private long sleepTime;

public ThreadLocalTest(String value, long delayTime, long sleepTime) {
this.value = value;
this.delayTime = delayTime;
this.sleepTime = sleepTime;
}

@Override
public void run() {
try {
Thread.sleep(this.delayTime);
System.out.println("[" + Thread.currentThread().getName() + "] is setting value [" + this.value + "] to [" + threadLocal + "]");
threadLocal.set(this.value);
Thread.sleep(this.sleepTime);
System.out.println("[" + Thread.currentThread().getName() + "] is accessing value [" + threadLocal.get() + "] from [" + threadLocal + "]");
} catch (InterruptedException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
ThreadLocalTest test1 = new ThreadLocalTest("V1", 0, 200);
ThreadLocalTest test2 = new ThreadLocalTest("V2", 100, 500);
Thread t1 = new Thread(test1, "thread1");
Thread t2 = new Thread(test2, "thread2");

t1.start();
t2.start();
}

}
[/quote]


InheritableThreadLocal:
使用之,可以让当前线程其子线程也共享 InheritableThreadLocal 内的数据。


Srcs:
正确理解ThreadLocal:
[url]http://www.iteye.com/topic/103804[/url]
ThreadLocal的几种误区
[url]http://www.blogjava.net/jspark/archive/2006/08/01/61165.html[/url]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值