最近围观@田麦大牛的代码,看到ThreadLocal还能这么玩,故此记录一下
ThreadLocal概念:http://blog.csdn.net/qjyong/article/details/2158097
可以明显看到ThreadLocal中的值是和线程本身绑定的,那么如果我在A线程中使用了ThreadLocal,set了一个变量,然后在B线程如何取出来呢。
往ThreadLocal中set变量时,可以debug这个类,发现类中除了一串hashCode外什么都没有,那么这个值究竟放在哪里呢?
threadLocalHashCode = -387276957
看一下ThreadLocal的set方法
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
可以看到ThreadLocal的变量全部是存储在Thread的
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
中,由于ThreadLocalMap是不可见的,所以只能通过反射的方式去调用。
到此为止,ThreadLocal就已经与线程并非完全相关了,你大可以对ThreadLocalMap进行copy,在采用事件回调等机制不同线程的情况下也可以run的很愉快了。完整代码如下:
public abstract class Task implements Runnable {
Object threadLocal;
public Task(Object threadLocalMap){
this.threadLocal =threadLocalMap;
}
public final void run(){
BeanUtils.forceSetProperties(Thread.currentThread(), threadLocal, "threadLocals");
realRun();
}
protected abstract void realRun();
}
例子:
public class ThreadLocalTest {
private static final ThreadLocal<String> tl = new ThreadLocal<String>();
static class MyTask extends Task{
public MyTask(Object threadLocal){
super(threadLocal);
}
@Override
public void realRun() {
System.out.println("I'm Thread:"+Thread.currentThread().getName()+", value is:"+tl.get());
}
}
public static void main(String[] args) {
tl.set("hello world");
Object threadLocals = BeanUtils.forceGetProperties(Thread.currentThread(),"threadLocals");
Executors.newSingleThreadExecutor().submit(new MyTask(threadLocals));
System.out.println("I'm Thread:"+Thread.currentThread().getName()+", value is:"+tl.get());
}
}
BeanUtils:
public static Object forceGetProperties(Object object, String fieldName){
try {
Field field = object.getClass().getDeclaredField(fieldName);
if (!field.isAccessible()){
field.setAccessible(true);
}
return field.get(object);
} catch (Exception e) {
//ignore
return null;
}
}
public static void forceSetProperties(Object target,Object arg, String fieldName){
try {
Field field = target.getClass().getDeclaredField(fieldName);
if (!field.isAccessible()){
field.setAccessible(true);
}
field.set(target,arg);
} catch (Exception e) {
//ignore
}
}
运行结果:
I'm Thread:main, value is:hello world
I'm Thread:pool-1-thread-1, value is:hello world
分享到:
相关推荐
- 局限:ThreadLocal并非万能解决方案,它不能解决跨线程的数据共享需求。此外,如果不及时清理ThreadLocal,可能导致内存泄漏。 5. **源码解析** 要深入理解ThreadLocal的工作原理,需要查看其源码。ThreadLocal...
- 不适用于跨线程通信:ThreadLocal只保证同一线程内的数据隔离,不同线程间无法共享ThreadLocal变量。 - 不是线程安全的:尽管ThreadLocal提供了线程隔离,但它本身并不保证线程安全性,如果在`set`和`get`操作之间...
通过 `HystrixRequestContext` 和相关的 API,Hystrix 能够有效地管理跨线程的数据传递,使得开发人员能够在使用线程池隔离模式时轻松地处理上下文数据。这种机制不仅提高了代码的可维护性和可读性,而且也增强了...
在多线程编程中,"跨线程提交数据"是一个重要的概念,特别是在并发处理和优化应用程序性能时。本文将深入探讨这一主题,旨在为初学者提供一个全面的理解。 首先,我们要明白什么是线程。线程是操作系统分配CPU时间...
- 虽然`ThreadLocal`能提供线程隔离,但不适用于跨线程的共享数据。 - `ThreadLocalMap`的扩容策略和哈希冲突处理不同于标准的`HashMap`,理解其内部机制有助于避免潜在的问题。 以上就是关于`ThreadLocal`及其内部...
因此,ThreadLocal不适合用于存储跨线程或者线程池中的共享数据。 **使用ThreadLocal的最佳实践** 1. **初始化和清理**:使用ThreadLocal时,应该在首次使用时进行初始化,并在不再需要时进行清理,避免内存泄漏。...
- **线程隔离性**:ThreadLocal只在创建它的线程内有效,无法跨线程共享数据。 - **难以调试**:由于ThreadLocal的隐式性,有时可能会导致难以发现的问题,特别是当线程池中的线程复用时。 ### 4. 使用注意事项 - ...
这时,ThreadLocal 的局限性就暴露出来了,即它不能解决跨线程池之间的数据传递问题。 为了解决这个问题,TransmittableThreadLocal 诞生了。TransmittableThreadLocal 是一种专门为线程池设计的ThreadLocal解决...
7. **局限性**:ThreadLocal不适合跨线程通信,如果需要在多个线程间共享数据,应该考虑使用其他机制,如线程安全的数据结构或通过消息传递。 在"ThreadLocal测试工程"中,通过`ThreadLocalTest`这个类,我们可以...
对于需要跨线程共享的数据,应该考虑使用锁或其他同步机制。ThreadLocal主要是为了隔离线程数据,而不是共享。 在实际开发中,ThreadLocal常常与装饰器结合使用,以便更方便地在函数级别控制线程局部变量。通过定义...
- 不要将ThreadLocal用作全局变量,因为它们只在创建它们的线程内有效,无法跨线程共享。 - 谨慎处理生命周期管理,尤其是在静态变量中使用ThreadLocal,确保在不再需要时正确清理,防止内存泄漏。 6. **应用场景...
5. **线程局部变量的局限性**:ThreadLocal并不是万能的解决方案,它不能解决所有线程间通信的问题,特别是对于需要跨线程共享数据的情况,ThreadLocal就无能为力了。此外,过度依赖ThreadLocal可能导致程序设计过于...
4. **缓存**:ThreadLocal可以用于实现线程级别的缓存,每个线程有自己的缓存,提高局部访问效率,减少跨线程同步的开销。 **ThreadLocal的使用实例:** 以下是一个简单的ThreadLocal使用示例: ```java public ...
在某些情况下,如数据需要跨线程共享,`ThreadLocal`就无能为力了。此外,如果不正确地管理`ThreadLocal`,可能会导致内存泄漏。当线程结束时,它所关联的`ThreadLocal`值并不会自动清除,因此如果主线程或守护线程...
2. **跨层传递参数**:在分层架构中,从高层到低层传递参数时,可以使用`ThreadLocal`避免参数的逐层传递。特别是当某个参数在较深层级的方法中被需要时,直接从`ThreadLocal`中获取比通过参数传递更为便捷。 **...
3. **线程局部性**:ThreadLocal的变量只存在于当前线程,跨线程无法访问,不适合需要跨线程共享数据的场景。 总结来说,ThreadLocal是Java中用于解决线程间数据隔离问题的有效工具,但需要谨慎使用,尤其是在处理...
如果线程结束,ThreadLocalMap及其所有的Entry都会被销毁,因此ThreadLocal不适用于跨线程持久化的数据存储。此外,如果线程长时间运行,而ThreadLocal未被清除,可能会导致内存泄漏,因为ThreadLocalMap不会自动...