资讯专栏INFORMATION COLUMN

java并发编程学习17--ThreadLocal

jayce / 1188人阅读

摘要:概念类用来存放线程的局部变量,每个线程都有自己的局部变量彼此之间不共享。返回当前线程的局部变量初始值。工作流程的时候我们可以看见是从中获取的,也就是说这些局部变量真正存储在中的时候从中获取到了,然后再从中获取。和都用于解决多线程并发访问。

【概念

ThreadLocal类用来存放线程的局部变量,每个线程都有自己的局部变量彼此之间不共享。TheadLocal主要有以下三个方法:

public T get():返回当前线程的局部变量。

protected T initValue():返回当前线程的局部变量初始值。默认情况下 initValue(), 返回 null 。线程在没有调用 set 之前,第一次调用 get 的时候, get 方法会默认去调用 initValue 这个方法。所以如果没有覆写这个方法,可能导致 get 返回的是 null 。当然如果调用过 set 就不会有这种情况了。

public void set(T value):设置当前线程的局部变量。

ThreadLocal是如何做到为每一个线程提供多带带的局部变量呢?实际上在ThreadLocal类中有一个Map缓存,用于存储每一个线程的局部变量。Map中元素的键为线程对象,而值对应线程的变量副本。

 /**
         * Construct a new map initially containing (firstKey, firstValue).
         * ThreadLocalMaps are constructed lazily, so we only create
         * one when we have at least one entry to put in it.
         */
        ThreadLocalMap(ThreadLocal firstKey, Object firstValue) {
            table = new Entry[INITIAL_CAPACITY];
            int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
            table[i] = new Entry(firstKey, firstValue);
            size = 1;
            setThreshold(INITIAL_CAPACITY);
        }
【工作流程

1.set()的时候:

 public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

我们可以看见ThreadLocalMap是从currentThread中获取的,也就是说这些局部变量真正存储在currentThread中:

void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

2.get()的时候:

 public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

从currentThread中获取到了ThreadLocalMap,然后再从中获取value。如果没有值,则调用setInitialValue()。

【如何使用
package ThreadLocal;

import java.util.Random;

import static ThreadLocal.ThreadLocalTest.localSetter;

/**
 * 在每个线程中多带带存放一个值然后再获取
 */
public class ThreadLocalTest {

    static ThreadLocal localSetter = new ThreadLocal();

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            MyThread t = new MyThread();
            t.start();
        }
    }
}
class MyThread extends Thread{

    private static Random random = new Random();

    @Override
    public void run(){
        //现在当前线程中存入一个随机变量 v1
        int randomVar = random.nextInt(100);
        localSetter.set(randomVar);
        System.out.println(getName() + " random is " + randomVar);
        //获取当前线程的随机变量 v2
        //v1 永远等于 v2
        System.out.println(getName() + " localVar is " + localSetter.get());
    }
}
【spring与ThreadLocal

spring中的bean大多都是单例的,但是我们应用又是支持并发的,所以将各个service,dao存放在ThreadLocal中是一个明智的做法。但是需要注意如果bean中包含共享变量,spring是没有做任何的安全处理的。

【synchronized与ThreadLocal

ThreadLocal以空间换取时间,提供了一种非常简便的多线程实现方式。
ThreadLocal和Synchonized都用于解决多线程并发访问。但是ThreadLocal与synchronized有本质的区别:
synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本。Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/68300.html

相关文章

  • Java多线程学习(七)并发编程中一些问题

    摘要:相比与其他操作系统包括其他类系统有很多的优点,其中有一项就是,其上下文切换和模式切换的时间消耗非常少。因为多线程竞争锁时会引起上下文切换。减少线程的使用。很多编程语言中都有协程。所以如何避免死锁的产生,在我们使用并发编程时至关重要。 系列文章传送门: Java多线程学习(一)Java多线程入门 Java多线程学习(二)synchronized关键字(1) java多线程学习(二)syn...

    dingding199389 评论0 收藏0
  • Java多线程学习(七)并发编程中一些问题

    摘要:因为多线程竞争锁时会引起上下文切换。减少线程的使用。举个例子如果说服务器的带宽只有,某个资源的下载速度是,系统启动个线程下载该资源并不会导致下载速度编程,所以在并发编程时,需要考虑这些资源的限制。 最近私下做一项目,一bug几日未解决,总惶恐。一日顿悟,bug不可怕,怕的是项目不存在bug,与其惧怕,何不与其刚正面。 系列文章传送门: Java多线程学习(一)Java多线程入门 Jav...

    yimo 评论0 收藏0
  • 超实用百道Java面试题

    摘要:是的简称,运行环境,为的运行提供了所需的环境。分割字符串,返回分割后的字符串数组。当计算的值相同时,我们称之为冲突,的做法是用链表和红黑树存储相同的值的。迭代器取代了集合框架中的,迭代器允许调用者在迭代过程中移除元素。 Java基础1.JDK和JRE有什么区别? JDK 是java development kit的简称,java开发工具包,提供java的开发环境和运行环境。JRE 是j...

    MkkHou 评论0 收藏0
  • java并发编程学习---之一

    摘要:开始学习也有一段时间了,一些基础的书也扫了一遍了。最近慢慢开始看和,后者的话和有类似之处,都是一些编程经验的编程的世界里好多的东西都是相同的。这里其实是对的最佳实践,之后该对象已经变成一个过期的引用了,此时就应该清空这个引用。 开始学习java也有一段时间了,一些基础的书也扫了一遍了(think in java/core java volume 1)。最近慢慢开始看和,后者的话和有类似...

    chavesgu 评论0 收藏0

发表评论

0条评论

jayce

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<