06_张孝祥_多线程_ThreadLocal类及应用技巧
来源:互联网 发布:无印良品文具淘宝 编辑:程序博客网 时间:2024/05/19 17:04
设计
ThreadLocal并不是包含Map对象,而是这些特定于线程的值保存在Thread对象中,java.lang.Thread定义了变量:ThreadLocal.ThreadLocalMap threadLocals = null
,当线程终止后,这些值会作为垃圾回收。
ThreadLocal.ThreadLocalMap
中定义Entry[] table
变量,Entry
类定义为Entry(ThreadLocal k, Object v)
,因此是线程java.lang.Thread
包含了所有的ThreadLocal及该ThreadLocal中该线程对应的值。
ThreadLocal.set()
创建新的Entry对象,并保存到ThreadLocal.ThreadLocalMap
变量Entry[] table
中 ThreadLocal.get()
时,各线程从自己的ThreadLocalMap对象变量Entry[] table
中取出与该ThreadLocal对应的Entry对象,并取出entry保存的值。
使用
JDK1.5提供了ThreadLocal类来方便实现线程范围内的数据共享,它的作用就相当于 05_张孝祥Java多线程线程范围内共享变量的概念与作用 中的Map(内部并不是Map),也就是让每个线程拥有自己的值
一个ThreadLocal对象只能记录一个线程内部的一个共享变量,需要记录多个共享数据,可以创建多个ThreadLocal对象,或者将这些数据进行封装,将封装后的数据对象存入ThreadLocal对象中。
线程结束后也可以自动释放相关的ThreadLocal变量,也可以调用ThreadLocal.remove()方法用来更快释放内存。
代码
下面用ThreadLocal类实现,替代 05_张孝祥Java多线程线程范围内共享变量的概念与作用 实现
import java.util.Random; public class ThreadLocalTest { private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(); 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(100); System.out.println(Thread.currentThread().getName()+" has put data: "+data); //往local里面设置值 threadLocal.set(data); new A().get(); new B().get(); } }).start(); } } static class A{ public void get(){ int data =threadLocal.get(); System.out.println("A from "+Thread.currentThread().getName()+" has get data: "+data); } } static class B{ public void get(){ int data =threadLocal.get(); System.out.println("B from "+Thread.currentThread().getName()+" has get data: "+data); } } }
假设需要保存不止一个值,可以把其他属性的值打包成一个类,然后将该类设置成ThreadLocal的值。
下面代码中,在类MyThreadLocalScopeDate里面定义了一个静态变量Map,用来保存所有线程创建的MyThreadLocalScopeDate,并使用单例使得不管多少线程都只创建一个MyThreadLocalScopeDate对象。
import java.util.Random; public class ThreadLocalTest { private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(); 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(100); System.out.println(Thread.currentThread().getName()+" has put data: "+data); //往local里面设置值 threadLocal.set(data); //获取自己线程的MyThreadLocalScopeDate实例对象 MyThreadLocalScopeDate myData = MyThreadLocalScopeDate.getThreadInstance(); myData.setName("name"+data); myData.setAge(data); new A().get(); new B().get(); } }).start(); } } static class A{ public void get(){ int data =threadLocal.get(); System.out.println("A from "+Thread.currentThread().getName()+" has get data: "+data); MyThreadLocalScopeDate myData = MyThreadLocalScopeDate.getThreadInstance(); System.out.println("A from "+Thread.currentThread().getName()+" has get MyThreadLocalScopeDate name: "+myData.getName()+" , age: "+myData.getAge()); } } static class B{ public void get(){ int data =threadLocal.get(); System.out.println("B from "+Thread.currentThread().getName()+" has get data: "+data); MyThreadLocalScopeDate myData = MyThreadLocalScopeDate.getThreadInstance(); System.out.println("B from "+Thread.currentThread().getName()+" has get MyThreadLocalScopeDate name: "+myData.getName()+" , age: "+myData.getAge()); } } } class MyThreadLocalScopeDate{//单例模式 private MyThreadLocalScopeDate(){};//构造方法私有化 private static ThreadLocal<MyThreadLocalScopeDate> map = new ThreadLocal<MyThreadLocalScopeDate>();//封装MyThreadLocalScopeDate是线程实现范围内共享 //思考AB两个线程过来的情况 自己分析 AB都需要的自己的对象 没有关系 所以不需要同步 如果有关系就需要同步了 public static /*synchronized*/MyThreadLocalScopeDate getThreadInstance(){ MyThreadLocalScopeDate instance =map.get(); if(instance==null){ instance = new MyThreadLocalScopeDate(); map.set(instance); } return instance; } 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; } }
参考
06.ThreadLocal类及应用技巧
正确理解ThreadLocal
多线程06_张孝祥-ThreadLocal类及应用技巧
- 06_张孝祥_多线程_ThreadLocal类及应用技巧
- 多线程06_张孝祥-ThreadLocal类及应用技巧
- 18_张孝祥_多线程_阻塞队列的应用
- 10_张孝祥_多线程_Callable与Future的应用
- 08_张孝祥_多线程_java5原子性操作类的应用
- 09_张孝祥_多线程_java5线程并发库的应用_线程池
- 多线程应用_打字游戏
- 06_多线程_生产者消费者
- 11_张孝祥_多线程_线程锁技术
- 17_张孝祥_多线程_同步工具Exchanger
- _多线程
- 日历类_应用
- 多线程应用_左圆右方
- Java_多线程_创建及启动线程
- Vim 文本编辑器_及使用技巧
- 黑马程序员_学习笔记5多线程在的应用遇到的主要问题及解决方法。
- 多线程_同步代码快的锁及同步方法应用和锁的问题
- C#_多线程_ 整理
- Git
- python
- 实现bitmap算法
- 什么是 MIME Type?
- 1.2 每一个对象都有一个接口
- 06_张孝祥_多线程_ThreadLocal类及应用技巧
- interrupte
- python代理ip抓取大众点评
- 标记语言Markdown介绍以及日常使用
- Kubernetes
- MyJdbcTemplate 常用的方法总结
- 执行远程调试jar命令
- 共享baidu.com,sohu.com,360.cn,qq.com,sina.com等二级域名
- [NOI2010]超级钢琴(可持续化线段树)