Java中的ThreadLocal学习理解


=Start=

缘由:

前段时间在用Java进行加解密的时候碰到了一个线程安全的问题,后来发现是因为对Java的Cipher包不熟悉导致,最后通过ThreadLocal的方式在正确性和性能上取得了一个平衡。

虽然问题是解决了,但是ThreadLocal是什么,以及为什么能解决这个问题我还不是特别清楚,所以就想专门学习一下ThreadLocal的相关知识,因为整体不算复杂,所以在收集、整理的过程中也就完成了相关知识的学习和介绍。

正文:

参考解答:
# ThreadLocal 是什么?

ThreadLocal是一个关于创建线程局部变量的类。ThreadLocal,很多地方叫做线程本地变量,也有些地方叫做线程本地存储,其实意思差不多。可能很多朋友都知道ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。

通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。而使用ThreadLocal创建的变量只能被当前线程访问,其他线程则无法访问和修改。

如何验证 threadLocal 确实是每个线程都创建了一个各自的副本?

public class ThreadLocalTest {
    ThreadLocal<Long> longLocal = new ThreadLocal<Long>();
    ThreadLocal<String> stringLocal = new ThreadLocal<String>();

    public void set() {
        longLocal.set(Thread.currentThread().getId());
        stringLocal.set(Thread.currentThread().getName());
    }

    public long getLong() {
        return longLocal.get();
    }

    public String getString() {
        return stringLocal.get();
    }

    public static void main(String[] args) throws InterruptedException {
        final ThreadLocalTest threadLocalTest = new ThreadLocalTest();
        
        threadLocalTest.set();
        System.out.println(threadLocalTest.getLong());
        System.out.println(threadLocalTest.getString());
        
        Thread thread1 = new Thread(){
            public void run() {
                threadLocalTest.set();
                System.out.println(threadLocalTest.getLong());
                System.out.println(threadLocalTest.getString());
            };
        };
        thread1.start();
        thread1.join();
         
        System.out.println(threadLocalTest.getLong());
        System.out.println(threadLocalTest.getString());
    }
}
# threadLocal 何时用?怎么用?
  • 最常见的ThreadLocal使用场景是用来解决数据库连接、Session管理等问题。
  • 还有就是密码算法中的 init 初始化操作,因为Java中的Cipher不是线程安全的,但是 init 又非常慢,所以比较适合。
# threadLocal 使用的注意事项?

1、先 set 再 get 否则可能会出异常,或者通过重写 initialValue 方法来避免此问题;

 

参考链接:

=END=

,

《 “Java中的ThreadLocal学习理解” 》 有 3 条评论

  1. ThreadLocal:Java中的影分身
    https://mp.weixin.qq.com/s/OzzAGVpFXCdVQyNmzLnNEw
    `
    希望可以通过这篇学习笔记来解决这几个问题:
    ThreadLocal是用来解决什么问题的?
    如何使用ThreadLocal?
    ThreadLocal的实现原理是什么?
    可否举几个实际项目中使用ThreadLocal的案例?
    `

  2. 手撕面试题ThreadLocal!!!
    https://mp.weixin.qq.com/s/8Ql-5kaUtxiCWyHR6uPPBw
    `
    ThreadLocal用在什么地方?
    如果仅仅就一个线程,那么都不用谈ThreadLocal的,ThreadLocal是用在多线程的场景的!
    ThreadLocal归纳下来就2类用途:
    1、保存线程上下文信息,在任意需要的地方可以获取!!!
    2、线程安全的,避免某些情况需要考虑线程安全必须同步带来的性能损失!!!

    ThreadLocal一些细节!
    Thread类有属性变量threadLocals (类型是ThreadLocal.ThreadLocalMap),也就是说每个线程有一个自己的ThreadLocalMap ,所以每个线程往这个ThreadLocal中读写隔离的,并且是互相不会影响的。
    一个ThreadLocal只能存储一个Object对象,如果需要存储多个Object对象那么就需要多个ThreadLocal!!!

    ThreadLocal的最佳实践!
    由于线程的生命周期很长,如果我们往ThreadLocal里面set了很大很大的Object对象,虽然set、get等等方法在特定的条件会调用进行额外的清理,但是ThreadLocal被垃圾回收后,在ThreadLocalMap里对应的Entry的键值会变成null,但是后续在也没有操作set、get等方法了。
    所以最佳实践,应该在我们不使用的时候,主动调用remove方法进行清理。
    `

  3. 惊:FastThreadLocal吞吐量居然是ThreadLocal的3倍!!!
    https://mp.weixin.qq.com/s/xJSmSexl8mzdX8ivSRAb6Q
    `
    关于FastThreadLocal,零度准备从这几个方面进行讲解:

    – FastThreadLocal的使用。
    – FastThreadLocal并不是什么情况都快,你要用对才会快。
    – FastThreadLocal利用字节填充来解决伪共享问题。
    – FastThreadLocal比ThreadLocal快,并不是空间换时间。
    – FastThreadLocal不在使用ObjectCleaner处理泄漏,必要的时候建议重写onRemoval方法。
    – FastThreadLocal为什么快?
    `

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注