一、概述
在java编程过程中,我们经常会遇到多线程的场景,因为在实际生产环境里面几乎是看不到单线程运行的,所有的业务程序都是多线程配合运行的。在单线程中,我们不需要考虑数据线程安全的问题,但是在多线程中,我们就需要考虑数据线程安全问题,因此在这里引入ThreadLocal对象。ThreadLocal就是在多线程的场景里面使用的。
二、ThreadLocal有什么用途?
第一种用途:在多线程中,保存线程上下文信息,方便线程在任何需要的地方都可以获取到。
第二种用途:线程安全的,避免某些情况需要考虑线程安全必须同步带来的性能损失。
三、ThreadLocal代码示例
3.1、创建一个Context对象
public class Context {
private String value = null;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}3.2、创建一个ThreadLocal来管理Context
public class ThreadLocalManager {
public static final ThreadLocal<Context> THREAD_LOCAL = new ThreadLocal<Context>();
public static void set(Context user) {
THREAD_LOCAL.set(user);
}
public static void unset() {
THREAD_LOCAL.remove();
}
public static Context get() {
return THREAD_LOCAL.get();
}
}3.3、编写一个子线程,写入和获取threadlocal的值
public class ThreadLocalTask implements Runnable {
@Override
public void run() {
try {
// 线程
Context context = new Context();
context.setValue(UUID.randomUUID().toString());
ThreadLocalManager.set(context);
// 打印线程和写入值
System.out.println(
"当前线程:" + Thread.currentThread().getName() + "把uuid写入了threadlocal中,写入值是:" + context.getValue());
// 睡10秒
TimeUnit.SECONDS.sleep(10);
// 睡10秒后,看下当前线程获取到的写入值是多少
Context lastValue = ThreadLocalManager.get();
System.out.println("当前线程:" + Thread.currentThread().getName() + "把从threadlocal中获取到的值是:" + lastValue.getValue());
ThreadLocalManager.unset();
} catch (Exception e) {
e.printStackTrace();
}
}
}3.4、编写测试类
public class ThreadLocalTest {
public static void main(String[] args) {
new Thread(new ThreadLocalTask()).start();
new Thread(new ThreadLocalTask()).start();
}
}3.5、查看执行结果
看到了吧,每一个线程只能获取到自己写入的值,不会获取到其他线程写入的值,从而保证线程安全性问题。
4、总结
1、由于不需要共享信息,自然就不存在竞争问题了,从而保证了某些情况下线程的安全,以及避免了某些情况需要考虑线程安全必须同步带来的性能损失!!!
2、每个线程往ThreadLocal中读写数据是线程隔离,互相之间不会影响的,所以ThreadLocal无法解决共享对象的更新问题!
5、细节
1、Threadlocal一般是放在一个公共的类里面使用的。
2、Threadlocal用完之后,一定要手动remove掉,避免oom,生产环境中一定要注意这一点,很多人都没有remove的习惯,导致生产环境容易出问题


还没有评论,来说两句吧...