一、概述
在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的习惯,导致生产环境容易出问题
还没有评论,来说两句吧...