返回顶部
首页 > 资讯 > 精选 >Java中ThreadLocal的原理是什么及怎么使用
  • 852
分享到

Java中ThreadLocal的原理是什么及怎么使用

2023-07-06 03:07:39 852人浏览 八月长安
摘要

这篇文章主要介绍“Java中ThreadLocal的原理是什么及怎么使用”,在日常操作中,相信很多人在Java中ThreadLocal的原理是什么及怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Jav

这篇文章主要介绍“Java中ThreadLocal的原理是什么及怎么使用”,在日常操作中,相信很多人在Java中ThreadLocal的原理是什么及怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中ThreadLocal的原理是什么及怎么使用”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

用法

  • 隔离各个线程间的数据

  • 避免线程内每个方法都进行传参,线程内的所有方法都可以直接获取到ThreadLocal中管理的对象。

package com.example.test1.service;import org.springframework.scheduling.annotation.Async;import org.springframework.stereotype.Component;import java.text.SimpleDateFORMat;import java.util.Date;@Componentpublic class AsyncTest {    // 使用threadlocal管理    private static final ThreadLocal<SimpleDateFormat> dateFormatLocal =            ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));    // 不用threadlocal进行管理,用于对比    SimpleDateFormat dateFormat = new SimpleDateFormat();    // 线程名称以task开头    @Async("taskExecutor")    public void formatDateSync(String format, Date date) throws InterruptedException {        SimpleDateFormat simpleDateFormat = dateFormatLocal.get();        simpleDateFormat.applyPattern(format);                // 所有方法都可以直接使用这个变量,而不用根据形参传入        doSomething();                Thread.sleep(1000);        System.out.println("sync " + Thread.currentThread().getName() +  " | " + simpleDateFormat.format(date));                // 线程执行完毕,清除数据        dateFormatLocal.remove();    }    // 线程名称以task2开头    @Async("taskExecutor2")    public void formatDate(String format, Date date) throws InterruptedException {        dateFormat.applyPattern(format);        Thread.sleep(1000);        System.out.println("normal " + Thread.currentThread().getName() +  " | " + dateFormat.format(date));    }}

使用junit进行测试

@Testvoid test2() throws InterruptedException {for(int index = 1; index <= 10; ++index){String format = index + "-yyyy-MM-dd";Date time = new Date();asyncTest.formatDate(format, time);}for(int index = 1; index <= 10; ++index){String format = index + "-yyyy-MM-dd";Date time = new Date();asyncTest.formatDateSync(format, time);}}

结果如下,可以看到没有被 ThreadLocal 管理的变量已经无法匹配正确的format。

sync task--10 | 10-2023-04-11
sync task--9 | 9-2023-04-11
normal task2-3 | 2-2023-04-11
normal task2-5 | 2-2023-04-11
normal task2-10 | 2-2023-04-11
normal task2-6 | 2-2023-04-11
sync task--1 | 1-2023-04-11
normal task2-7 | 2-2023-04-11
normal task2-8 | 2-2023-04-11
normal task2-9 | 2-2023-04-11
sync task--6 | 6-2023-04-11
sync task--3 | 3-2023-04-11
sync task--2 | 2-2023-04-11
sync task--7 | 7-2023-04-11
sync task--4 | 4-2023-04-11
sync task--8 | 8-2023-04-11
normal task2-4 | 2-2023-04-11
normal task2-1 | 2-2023-04-11
sync task--5 | 5-2023-04-11
normal task2-2 | 2-2023-04-11

实现原理

ThreadLocal中获取数据的过程:

先获取对应的线程。

通过 getMap(t)拿到线程中的 ThreadLocalMap

ThreadLocalMap 是一个重新实现的散列表,基于两个元素实现散列:

  • 用户定义的ThreadLocal对象,例如:dateFormatLocal

  • 封装了valueEntry对象。

通过map.getEntry(this)方法,根据当前的 threadlocal对象在散列表中获得对应的Entry

如果是第一次使用get(), 则使用 setInitialValue()调用用户重写的initialValue()方法创建map并使用用户指定的值初始化。

在这种设计方式下,线程死去的时候,线程共享变量ThreadLocalMap会被销毁。

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();}

注意 Entry对象是弱引用:

static class Entry extends WeakReference<ThreadLocal<?>> {        Object value;    // k: ThreadLocal, v: value    Entry(ThreadLocal<?> k, Object v) {        super(k);        value = v;    }}

弱引用的常见用法是:

WeakReference<RoleDTO> weakReference = new WeakReference<>(new RoleDTO());

因此,在Entry中,k 代表ThreadLocal对象,它是弱引用。v代表ThreadLocal管理的那个value,是强引用。

内存泄漏

内存泄漏是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成内存空间的浪费称为内存泄漏。随着垃圾回收器活动的增加以及内存占用的不断增加,程序性能会逐渐表现出来下降,极端情况下,会引发OutOfMemoryError导致程序崩溃。

内存泄漏问题主要在线程池中出现,因为线程池中的线程是不断执行的,从任务队列中不断获取新的任务执行。但是任务中可能有ThreadLocal对象,这些对象的ThreadLocal会保存在线程的ThreadLocalMap中,因此ThreadLocalMap会越来越大。

但是ThreadLocal是由任务(worker)传入的,一个任务执行结束后,对应的ThreadLocal对象会被销毁。线程中的关系是: Thread -> ThreadLoalMap -> Entry<ThreadLocal, Object>ThreadLocal由于是弱引用会,在GC的时候会被销毁,这会导致 ThreadLoalMap中存在Entry<null, Object>

使用remove()

由于线程池中的线程一直在运行,如果不对ThreadLoalMap进行清理,那Entry<null, Object>会一直占用内存。remove()方法会清除key==nullEntry

使用static修饰

ThreadLocal设置成static可以避免一个线程类多次传入线程池后重复创建Entry。例如,有一个用户定义的线程

public class Test implements Runnable{    private static ThreadLocal<Integer> local = new ThreadLocal<>();    @Override    public void run() {        // do something    }}

使用线程池处理10个任务。那么线程池中每个用来处理任务的线程的Thread.ThreadLocalMap中都会保存一个Entry<local, Integer>,由于添加了static关键字,所有每个线程中的Entry中的local变量引用的都是同一个变量。这时就算发生内存泄漏,所有的Test类也只有一个local对象,不会导致内存占用过多。

@Testvoid contextLoads() {   Runnable runnable = () -> {      System.out.println(Thread.currentThread().getName());   };   for(int index = 1; index <= 10; ++index){      taskExecutor2.submit(new com.example.test1.service.Test());   }}

到此,关于“Java中ThreadLocal的原理是什么及怎么使用”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: Java中ThreadLocal的原理是什么及怎么使用

本文链接: https://lsjlt.com/news/357564.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Java中ThreadLocal的原理是什么及怎么使用
    这篇文章主要介绍“Java中ThreadLocal的原理是什么及怎么使用”,在日常操作中,相信很多人在Java中ThreadLocal的原理是什么及怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Jav...
    99+
    2023-07-06
  • Java中ThreadLocal的用法和原理是什么
    这篇文章主要介绍“Java中ThreadLocal的用法和原理是什么”,在日常操作中,相信很多人在Java中ThreadLocal的用法和原理是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中Th...
    99+
    2023-07-06
  • ThreadLocal工作原理及用法是什么
    今天就跟大家聊聊有关ThreadLocal工作原理及用法是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。ThreadLocal是什么ThreadLocal是线程Thread中属性...
    99+
    2023-06-22
  • ThreadLocal的原理和使用场景是什么
    ThreadLocal是Java中的一个类,用于在多线程环境中实现线程内部的数据共享。它提供了一个线程局部变量,每个线程都可以独立地...
    99+
    2023-09-12
    ThreadLocal
  • Java多线程之ThreadLocal的原理是什么
    今天小编给大家分享一下Java多线程之ThreadLocal的原理是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1、什...
    99+
    2023-07-06
  • java中的ThreadLocal是什么
    这篇文章将为大家详细讲解有关java中的ThreadLocal是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。简单介绍ThreadLocal一般称为线程本地变量,它是一种特殊的线程绑定机制,将变量与线...
    99+
    2023-06-19
  • java中ThreadLocal是什么
    ThreadLocal是JDK包提供的,称为线程本地变量,它将变量与线程绑定在一起,为每一个线程维护一个独立的变量副本,通过ThreadLocal可以将对象的可见范围限制在同一个线程内,从而避免了线程安全问题,对解决多线程程序的并发问题有一...
    99+
    2024-04-02
  • Java中ThreadLocal线程变量的实现原理是什么
    这篇文章主要介绍了Java中ThreadLocal线程变量的实现原理是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java中ThreadLocal线程变量的实现原理是什么文章都会有所收获,下面我们一起来看...
    99+
    2023-07-02
  • ThreadLocal的set方法原理是什么
    这篇文章主要介绍了ThreadLocal的set方法原理是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇ThreadLocal的set方法原理是什么文章都会有所收获,下面我们一起来看看吧。前沿知识Threa...
    99+
    2023-07-05
  • Java中AQS的原理及作用是什么
    这篇文章主要介绍“Java中AQS的原理及作用是什么”,在日常操作中,相信很多人在Java中AQS的原理及作用是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中AQS的原理及作用是什么”的疑惑有所...
    99+
    2023-06-15
  • Java中ThreadLocal类怎么使用
    这篇文章主要介绍“Java中ThreadLocal类怎么使用”,在日常操作中,相信很多人在Java中ThreadLocal类怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中ThreadLoca...
    99+
    2023-06-29
  • ThreadLocal怎么在Java中使用
    今天就跟大家聊聊有关ThreadLocal怎么在Java中使用 ,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。一.对ThreadLocal的理解ThreadLocal,很多地方叫做线...
    99+
    2023-05-31
    java threadlocal ava
  • Java中ThreadLocal导致内存OOM的原因是什么
    本篇内容介绍了“Java中ThreadLocal导致内存OOM的原因是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!原因分析Thread...
    99+
    2023-06-30
  • Java线程池实现原理是什么及怎么使用
    这篇文章主要讲解了“Java线程池实现原理是什么及怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java线程池实现原理是什么及怎么使用”吧!1. 为什么要使用线程池使用线程池通常由以...
    99+
    2023-07-04
  • Java中的ThreadLocal怎么用
    这篇文章给大家分享的是有关Java中的ThreadLocal怎么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。引言ThreadLocal的官方API解释为:“该类提供了线程局部 (thread-local) &...
    99+
    2023-06-17
  • ThreadLocal原理分析及应用场景是怎样的
    本篇文章给大家分享的是有关ThreadLocal原理分析及应用场景是怎样的,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。1. ThreadLocal是什么?有哪些用途?首先介绍...
    99+
    2023-06-22
  • Java中ThreadLocal有什么用
    这篇文章将为大家详细讲解有关Java中ThreadLocal有什么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、ThreadLocal简介多线程访问同一个共享变量的时候容易出现并发问题,特别是多个线...
    99+
    2023-06-15
  • java中ThreadLocal怎么用
    这篇文章将为大家详细讲解有关java中ThreadLocal怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。package test;public class Threa...
    99+
    2023-06-02
  • Java中ThreadLocal的用法和原理详解
    目录用法实现原理内存泄漏用法 隔离各个线程间的数据避免线程内每个方法都进行传参,线程内的所有方法都可以直接获取到ThreadLocal中管理的对象。 package com.exam...
    99+
    2023-05-15
    Java ThreadLocal用法 Java ThreadLocal原理 Java ThreadLocal
  • Python迭代器的原理是什么及怎么使用
    这篇文章主要介绍了Python迭代器的原理是什么及怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Python迭代器的原理是什么及怎么使用文章都会有所收获,下面我们一起来看看吧。什么是迭代器能被 next...
    99+
    2023-06-30
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作