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引用的对象
- 基础
- 编译和安装
- scanner类(键盘录入)
- Random类(随机数)
- 数组
- 方法
- 类
- ArrayList集合
- char与int
- eclipse
- IDEA
- 变量与常量
- 常用API
- String,StringBuffer,StringBuilder
- 正则,Date,DateFormat,Calendar
- 包装类,System,Math,Arrays,BigInteger,BigDecimal
- 集合,迭代器,增强for,泛型
- List,set,判断集合唯一
- map,Entry,HashMap,Collections
- 异常
- IO
- File
- 递归
- 字节流
- 字符流
- IO流分类
- 转换流
- 缓冲流
- 流的操作规律
- properties
- 序列化流与反序列化流
- 打印流
- commons-IO
- IO流总结
- 多线程
- 线程池
- 线程安全
- 线程同步
- 死锁
- lock接口
- ThreadLoad
- 等待唤醒机制
- 线程状态
- jdbc
- DBUtils
- 连接池DBCP
- c3p0连接池
- 网络编程
- 多线程socket上传图片
- 反射
- xml
- 设计模式
- 装饰器模式
- web service
- tomcat
- Servlet
- response
- request
- session和cookie
- JSP
- EL
- JSTL
- 事务
- 监听器Listener
- 过滤器Filter
- json
- linux安装软件
- 反射详解
- 类加载器和注解
- 动态代理
- jedis
- Hibernate
- 简介
- 创建映射文件
- Hibernate核心配置文件
- 事务和增删改查
- HibernateUtils
- 持久化对象的三种状态
- 检索方式
- query
- Criteria
- SQLQuery
- 持久化类
- 主键生成策略
- 缓存
- 事务管理
- 关系映射
- 注解
- 优化
- struts2
- 搭建
- 配置详解
- Action
- 结果跳转方式
- 访问ServletAPI方式
- 如何获得参数
- OGNL表达式
- valueStack 值栈
- Interceptor拦截器
- spring
- 导包
- IOC和DI
- Bean获取与实例化
- Bean属性注入
- spring注解
- 注解分层
- junit整合
- aop
- 动态代理实现
- cglib代理实现
- aop名词
- spring的aop
- aop-xml详解
- aop-注解详解
- 代理方式选择
- jdbcTemplate
- spring事务管理
- 回滚注意
- 事务传播属性
- MyBatis
- MyBatis简介
- 入门程序
- 与jdbc hibernate不同
- 原始Dao开发
- Mapper动态代理方式
- SqlMapConfig.xml配置文件
- 输入参数pojo包装类
- resultMap
- 动态sql
- 一对一关联
- 一对多
- 整合spring
- 逆向工程
- maven
- maven简介
- 仓库
- maven目录结构
- maven常用命令
- 生命周期
- eclipse中maven插件
- 入门程序
- 整合struct
- 依赖范围
- 添加插件
- idea配置
- jar包冲突
- 分模块开发
- 构建可执行的jar包(包含依赖jar包)
- springMVC
- 处理流程
- java面试
- java版本升级
- java1-8版本变更
- java9新特性
- 锁
- java资料
- idea
- jdk版本切换
- log4j
- 入门实例
- 基本使用方法
- Web中使用Log4j
- spring中使用log4j
- java代码优化