Java中ThreadLocal模拟和解释

本文涉及的产品
数据可视化DataV,5个大屏 1个月
可视分析地图(DataV-Atlas),3 个项目,100M 存储空间
简介:

一、测试代码

public class XY_ThreadData

{

private static Integer data = 0;

private static Map<Thread, Integer> map = new HashMap<Thread, Integer>();

private static ThreadLocal<Integer> local = new ThreadLocal<Integer>();

public static void setData(Integer value)

{

 data = value;

}

public static Integer getData()

{

 System.out.println("ThreadName:" + Thread.currentThread() + " data value:" + data);

 return data;

}

public static void setMapData(Integer value)

{

 map.put(Thread.currentThread(), value);

}

public static Integer getMapData()

{

 Object obj = map.get(Thread.currentThread());

 System.out.println("ThreadName:" + Thread.currentThread() + "map value:" + obj);

 return Integer.parseInt(obj.toString());

}

public static void setThreadLocalData(Integer value)

{

 local.set(value);

}

public static Integer getThreadLocalData()

{

 Object obj = local.get();

 System.out.println("ThreadName:" + Thread.currentThread() + "threadlocal value:" + obj);

 return Integer.parseInt(obj.toString());

}

}

public class XY_ThreadData_Test

{

public static void main(String[] args)

{

 for (int i = 0; i < 10; i++)

 {

  new Thread(new Runnable() {

   public void run()

   {

    final int value = new Random().nextInt(); // 每个线程自己创建的变量  

    XY_ThreadData.setData(value);

    XY_ThreadData.getData();

   }

  }).start();

 }

}

}

ThreadName:Thread[Thread-3,5,main] data value:1046062244

ThreadName:Thread[Thread-6,5,main] data value:-879673875

ThreadName:Thread[Thread-2,5,main] data value:-125397465

ThreadName:Thread[Thread-4,5,main] data value:-1546413071

ThreadName:Thread[Thread-0,5,main] data value:754770101

ThreadName:Thread[Thread-8,5,main] data value:-1666786926

ThreadName:Thread[Thread-5,5,main] data value:-1666786926

ThreadName:Thread[Thread-9,5,main] data value:1046062244

ThreadName:Thread[Thread-1,5,main] data value:269410746

ThreadName:Thread[Thread-7,5,main] data value:269410746

分析:可以看到以下两个线程中data的值时一样的,没有做到各个线程变量独一份

ThreadName:Thread[Thread-8,5,main] data value:-1666786926

ThreadName:Thread[Thread-5,5,main] data value:-1666786926


public class XY_ThreadData_Test

{

public static void main(String[] args)

{

 for (int i = 0; i < 10; i++)

 {

  new Thread(new Runnable() {

   public void run()

   {

    final int value = new Random().nextInt();  

    XY_ThreadData.setMapData(value);

    XY_ThreadData.getMapData();

   }

  }).start();

 }

}

}

ThreadName:Thread[Thread-0,5,main]map value:-1138167111

ThreadName:Thread[Thread-4,5,main]map value:-1545929782

ThreadName:Thread[Thread-6,5,main]map value:-1612385717

ThreadName:Thread[Thread-3,5,main]map value:-1390594683

ThreadName:Thread[Thread-8,5,main]map value:518506934

ThreadName:Thread[Thread-2,5,main]map value:1583239372

ThreadName:Thread[Thread-5,5,main]map value:995578601

ThreadName:Thread[Thread-1,5,main]map value:-916627474

ThreadName:Thread[Thread-7,5,main]map value:-960206804

ThreadName:Thread[Thread-9,5,main]map value:-1187504747

分析:模拟线程变量独一份,无重复


public class XY_ThreadData_Test

{

public static void main(String[] args)

{

 for (int i = 0; i < 10; i++)

 {

  new Thread(new Runnable() {

   public void run()

   {

    final int value = new Random().nextInt();

    XY_ThreadData.setThreadLocalData(value);

    XY_ThreadData.getThreadLocalData();

   }

  }).start();

 }

}

}

ThreadName:Thread[Thread-1,5,main]threadlocal value:935024745

ThreadName:Thread[Thread-4,5,main]threadlocal value:1207176846

ThreadName:Thread[Thread-7,5,main]threadlocal value:-1503260374

ThreadName:Thread[Thread-9,5,main]threadlocal value:-1538563684

ThreadName:Thread[Thread-6,5,main]threadlocal value:955259906

ThreadName:Thread[Thread-8,5,main]threadlocal value:894428541

ThreadName:Thread[Thread-3,5,main]threadlocal value:730986356

ThreadName:Thread[Thread-2,5,main]threadlocal value:-540225655

ThreadName:Thread[Thread-5,5,main]threadlocal value:-2003809947

ThreadName:Thread[Thread-0,5,main]threadlocal value:1917431015

分析:线程变量独一份,无重复


二、ThreadLocal分析

要点1

ThreadLocal不是用来解决共享对象的多线程访问问题的,一般情况下通过ThreadLocal.set()到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。各个线程中访问的是不同的对象。


要点2

说ThreadLocal使得各线程能够保持各自独立的一个对象,并不是通过ThreadLocal.set()来实现的,而是通过每个线程中的new对象的操作来创建的对象,每个线程创建一个,不是什么对象的拷贝或副本。通ThreadLocal.set()将这个新创建的对象的引用保存到各线程的自己的一个map中,每个线程都有这样一个map,执行ThreadLocal.get()时,各线程从自己的map中取出放进去的对象,因此取出来的是各自自己线程中的对象,ThreadLocal实例是作为map的key来使用的。


要点3

如果ThreadLocal.set()进去的东西本来就是多个线程共享的同一个对象,那么多个线程的ThreadLocal.get()取得的还是这个共享对象本身,还是有并发访问问题。


更多关于ThreadLocal信息请参看:http://www.iteye.com/topic/103804

本文转自IT徐胖子的专栏博客51CTO博客,原文链接http://blog.51cto.com/woshixy/1275284如需转载请自行联系原作者


woshixuye111

相关实践学习
DataV Board用户界面概览
本实验带领用户熟悉DataV Board这款可视化产品的用户界面
阿里云实时数仓实战 - 项目介绍及架构设计
课程简介 1)学习搭建一个数据仓库的过程,理解数据在整个数仓架构的从采集、存储、计算、输出、展示的整个业务流程。 2)整个数仓体系完全搭建在阿里云架构上,理解并学会运用各个服务组件,了解各个组件之间如何配合联动。 3&nbsp;)前置知识要求 &nbsp; 课程大纲 第一章&nbsp;了解数据仓库概念 初步了解数据仓库是干什么的 第二章&nbsp;按照企业开发的标准去搭建一个数据仓库 数据仓库的需求是什么 架构 怎么选型怎么购买服务器 第三章&nbsp;数据生成模块 用户形成数据的一个准备 按照企业的标准,准备了十一张用户行为表 方便使用 第四章&nbsp;采集模块的搭建 购买阿里云服务器 安装 JDK 安装 Flume 第五章&nbsp;用户行为数据仓库 严格按照企业的标准开发 第六章&nbsp;搭建业务数仓理论基础和对表的分类同步 第七章&nbsp;业务数仓的搭建&nbsp; 业务行为数仓效果图&nbsp;&nbsp;
相关文章
|
4月前
|
缓存 Java 程序员
Java面试题:解释强引用、软引用、弱引用和虚引用在Java中是如何工作的?
Java面试题:解释强引用、软引用、弱引用和虚引用在Java中是如何工作的?
36 1
|
4月前
|
Java 应用服务中间件 开发者
Java面试题:解释Spring Boot的优势及其自动配置原理
Java面试题:解释Spring Boot的优势及其自动配置原理
117 0
|
2月前
|
算法 安全 Java
JAVA并发编程系列(12)ThreadLocal就是这么简单|建议收藏
很多人都以为TreadLocal很难很深奥,尤其被问到ThreadLocal数据结构、以及如何发生的内存泄漏问题,候选人容易谈虎色变。 日常大家用这个的很少,甚至很多近10年资深研发人员,都没有用过ThreadLocal。本文由浅入深、并且才有通俗易懂方式全面分析ThreadLocal的应用场景、数据结构、内存泄漏问题。降低大家学习啃骨头的心理压力,希望可以帮助大家彻底掌握并应用这个核心技术到工作当中。
|
3月前
|
存储 安全 Java
Java 中的 ThreadLocal 变量
【8月更文挑战第22天】
38 4
|
4月前
|
存储 SQL Java
(七)全面剖析Java并发编程之线程变量副本ThreadLocal原理分析
在之前的文章:彻底理解Java并发编程之Synchronized关键字实现原理剖析中我们曾初次谈到线程安全问题引发的"三要素":多线程、共享资源/临界资源、非原子性操作,简而言之:在同一时刻,多条线程同时对临界资源进行非原子性操作则有可能产生线程安全问题。
|
4月前
|
存储 安全 Java
Java面试题:请解释Java内存模型(JMM)是什么,它如何保证线程安全?
Java面试题:请解释Java内存模型(JMM)是什么,它如何保证线程安全?
108 13
|
4月前
|
存储 Java 程序员
Java面试题:请解释Java中的永久代(PermGen)和元空间(Metaspace)的区别
Java面试题:请解释Java中的永久代(PermGen)和元空间(Metaspace)的区别
208 11
|
4月前
|
Java 测试技术 开发者
Java面试题:解释CountDownLatch, CyclicBarrier和Semaphore在并发编程中的使用
Java面试题:解释CountDownLatch, CyclicBarrier和Semaphore在并发编程中的使用
70 11
|
4月前
|
缓存 安全 Java
Java面试题:解释volatile关键字的作用,以及它如何保证内存的可见性
Java面试题:解释volatile关键字的作用,以及它如何保证内存的可见性
74 4
|
4月前
|
监控 算法 Java
Java面试题:如何在Java中触发一次Full GC?请详细解释垃圾回收机制和知识
Java面试题:如何在Java中触发一次Full GC?请详细解释垃圾回收机制和知识
356 4