多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
http://blog.csdn.net/iktz_cn/article/details/50118695 通过ThreadLoad实现线程范围内的共享变量 线程共享变量可能出现的问题 ![](https://box.kancloud.cn/86fd13693a6cfcf9c6ffd53c6533f419_1282x818.png) 使用ThreadLocal来避免共享变量的并发问题 ![](https://box.kancloud.cn/1afcd1599906b22bceff4b61295a80c4_1354x820.png) 实例代码 ~~~ package cn.iktz.thread.demo; import java.util.Random; public class ThreadLocalTest2 { public static void main(String[] args) { for (int i = 0; i < 2; i++) { new Thread(new ThreadLocalTestSetData()).start(); } } } class Object1 { public void get(ThreadLocal<Integer> x) { System.out.println("A from " + Thread.currentThread().getName() + " get data :" + x.get()); } } class ThreadLocalTestSetData implements Runnable { private ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(); @Override public void run() { int data = new Random().nextInt(); System.out.println(Thread.currentThread().getName() + " has put data :" + data); threadLocal.set(data);// threadLocl用来存储数据,存储的数据与当前线程有关的而非全局的 MyThreadScopeData.getThreadInstance().setName("name" + data); MyThreadScopeData.getThreadInstance().setAge(data); new Object1().get(threadLocal); } } ~~~ 对ThreadLocal进行封装 ~~~ package cn.iktz.thread.demo; import java.util.Random; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ThreadLocalTest3 { public static void main(String[] args) { for (int i = 0; i < 2; i++) { new Thread(new Runnable() { @Override public void run() { int data = new Random().nextInt(); System.out.println(Thread.currentThread().getName() + " has put data :" + data); MyThreadScopeData.getThreadInstance().setName("name" + data); MyThreadScopeData.getThreadInstance().setAge(data); new A().get(); } }).start(); } } static class A { public void get() { MyThreadScopeData myData = MyThreadScopeData.getThreadInstance(); System.out.println("A from " + Thread.currentThread().getName() + " getMyData: " + myData.getName() + "," + myData.getAge()); } } static class MyThreadScopeData { private MyThreadScopeData() { } static Lock lock = new ReentrantLock(); public static MyThreadScopeData getThreadInstance() { lock.lock(); try { MyThreadScopeData instance = map.get(); if (instance == null) { instance = new MyThreadScopeData(); /** 这里可能会出现并发问题,所以要加锁。 这里如果a线程创建了对象,并赋值,此时instance指向0X6666, 然后b来了get为null,也会创建一个对象并赋值,此时instance指向0x7777,0x6666被覆盖 b线程放入了0x7777的对象,此时切换到a线程,a也会放入0x7777的对象,则出现并发问题 */ map.set(instance); } return instance; } finally{ lock.unlock(); } } private static ThreadLocal<MyThreadScopeData> map = new ThreadLocal<MyThreadScopeData>(); private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } } ~~~ 线程退出时清空该线程ThreadLocal的数据,看api可以知道,gc线程,会回收只被ThreadLocal引用的对象