iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >ThreadLocal使用方法是什么
  • 793
分享到

ThreadLocal使用方法是什么

2023-06-29 02:06:27 793人浏览 独家记忆
摘要

这篇“ThreadLocal使用方法是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“ThreadLocal使用方法是什么

这篇“ThreadLocal使用方法是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“ThreadLocal使用方法是什么”文章吧。

一、常见场景

ThreadLocal作为线程上下文副本,那么一种最常见的使用方式就是用来方法隐式传参,通过提供的set()和get()两个public方法来实现在不同的方法中的参数传递。对于编程规范来说,方法定义的时候是对参数个数是有限制的,甚至在一些大厂,对方法参数个数是有明确规定的。

线程安全,每个线程维持自己的变量,以免紊乱,像常用的数据库的连接池的线程安全实现就使用了ThreadLocal。

二、进阶使用

以参数传递为例子,如何更好地使用ThreadLocal来实现在同一线程栈中不同方法中的参数传递。在参数传递的时候,那么都会有参数名,参数值,而ThreadLocal提供的get()和set()方法,不能直接满足设置参数名和参数值。这种情况下就需要对ThreadLocal进一次封装,如下代码,维护一个map对象,然后提供setValue(key, value)和getValue(key, value)方法,就可以很方便地实现了参数的设置和获取;在需要的地方对参数进行清理,使用remove(key)或者clear()即可实现。

import java.util.HashMap;import java.util.Map; public class ThreadLocalManger<T> extends ThreadLocal<T> {     private static ThreadLocalManger<Map<String, Object>> MANGER = new ThreadLocalManger<>();     private static HashMap<String, Object> MANGER_MAP = new HashMap<>();     public static void setValue(String key, Object value) {        Map<String, Object> context = MANGER.get();        if(context == null) {            synchronized (MANGER_MAP) {                if(context == null) {                    context = new HashMap<>();                    MANGER.set(context);                }            }        }        context.put(key, value);    }     public static Object getValue(String key) {        Map<String, Object> context = MANGER.get();        if(context != null) {            return context.get(key);        }        return null;    }     public static void remove(String key) {        Map<String, Object> context = MANGER.get();        if(context != null) {            context.remove(key);        }    }     public static void clear() {        Map<String, Object> context = MANGER.get();        if(context != null) {            context.clear();        }    }}

三、使用漏洞

继续以参数传递为例子,来看看ThreadLocal使用过程中存在的问题和后果。在实际业务的功能开发中,为了提升效率,大部分情况下都会使用线程池来实现,比如数据库的连接池、rpc请求连接池、MQ消息处理池、后台批量job池等等;同时也可能会使用一个伴随整个应用生命周期的线程(守护线程)来实现的一些功能,比如说心跳、监控等等。使用线程池,那么在实际生产业务中并发肯定不低,池中线程就会一直复用;守护线程一旦创建,那么就会活到应用停机。所以在这些情况下,线程的生命周期很长,在使用ThreadLocal的时候,一定要进行清理,不然就会有内存溢出的情况发生。通过以下案例来模拟内存溢出的情况。

通过一个死循环来模拟高并发场景。创建一个10个核心线程数,10个最大线程数数,60秒空闲时间的、线程名以ThreadLocal-demo-开头的线程池,在该场景下,将有10个线程来运行,运行内容很简单:生成一个UUID,并将其作为参数key,然后设置到线程副本中。

import org.springframework.scheduling.concurrent.CustomizableThreadFactory;import org.springframework.stereotype.Service; import java.util.UUID;import java.util.concurrent.*; @Servicepublic class ThreadLocalService {     ThreadFactory springThreadFactory = new CustomizableThreadFactory("TheadLocal-demo-");     ExecutorService executorService = new ThreadPoolExecutor(10, 10, 60,            TimeUnit.SECONDS, new LinkedBlockingQueue<>(), springThreadFactory);     ExecutorService service = new ThreadPoolExecutor(10, 10, 60,            TimeUnit.SECONDS, new LinkedBlockingQueue<>());     public Object setValue() {        for(; ;) {            try {                Runnable runnable = new Runnable() {                    @Override                    public void run() {                        String id = UUID.randomUUID().toString();                        // add                        ThreadLocalManger.setValue(id, "this is a value");                        //do something here                        ThreadLocalManger.getValue(id);                        // clear()                        //ThreadLocalManger.clear();                    }                };                executorService.submit(runnable);            } catch (Exception e) {                e.printStackTrace();                break;            }        }        return "success";    } }

以上代码中已把clear()方法注释掉,不做清理,触发程序,稍微将JVM设置低一些,跑不久就会报如下OOM。

java.lang.OutOfMemoryError: GC overhead limit exceededException in thread "TheadLocal-demo-9" Exception in thread "TheadLocal-demo-8" Exception in thread "TheadLocal-demo-6" Exception in thread "TheadLocal-demo-10" Exception in thread "TheadLocal-demo-7" java.lang.OutOfMemoryError: GC overhead limit exceededException in thread "TheadLocal-demo-5" java.lang.OutOfMemoryError: GC overhead limit exceededjava.lang.OutOfMemoryError: GC overhead limit exceededjava.lang.OutOfMemoryError: GC overhead limit exceeded    at com.intellij.rt.debugger.agent.CaptureStorage.insertEnter(CaptureStorage.java:57)    at java.util.concurrent.FutureTask.run(FutureTask.java)    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)    at java.lang.Thread.run(Thread.java:748)java.lang.OutOfMemoryError: GC overhead limit exceededjava.lang.OutOfMemoryError: GC overhead limit exceeded

就会发生严重的内存溢出,通过如下debug截图可知,设置进去的UUID堆积在内存中,逐步变多,最终撑爆内存。

ThreadLocal使用方法是什么

 在实际的业务场景中,需要传递的可能有订单号,交易号,流水号等等,这些变量往往是唯一不重复的、符合案例中的UUID情况,在不清理的情况下就会造成应用OOM,进而不可用;在分布式系统中,还能导致上下游系统不可用,进而导致整个分布式进去的不可用;如果这些信息往往还可能用在网络传输中,大消息占有网络带宽,严重甚至导致网络瘫痪。所以一个小小的细节就会置整个集群于危险之中,那么如何合理化解呢。

四、终阶使用

以上问题在于忘记清理,那么如何让清理无感知,即不需要清理也没有问题。根因在于线程跑完一次之后,没有进行清理,所以可提供一个基类线程,在线程执行最后对清理进行封装。如下代码。提供一个BaseRunnable抽象基类,该类主要如下特点。

        1、该类继承Runnable。

        2、实现setArg(key, value)和getArg(key)两个方法。

        2、在重写的run方式中分为两步,第一步,调用抽象方法task;第二步,清理线程副本。

有了以上3个特点,继承了BaseRunnable的线程类,只需要在实现task方法,在task方法中实现业务逻辑,参数传递和获取通过setArg(key, value)和getArg(key)两个方法即可实现,无需再显示清理。

public abstract class BaseRunnable implements Runnable {     @Override    public void run() {        try {            task();        } finally {            ThreadLocalManger.clear();        }    }     public void setArg(String key, String value) {        ThreadLocalManger.setValue(key, value);    }     public Object getArg(String key) {        return ThreadLocalManger.getValue(key);    }     public abstract void task();}

以上就是关于“ThreadLocal使用方法是什么”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程网精选频道。

--结束END--

本文标题: ThreadLocal使用方法是什么

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

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

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • ThreadLocal使用方法是什么
    这篇“ThreadLocal使用方法是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“ThreadLocal使用方法是什么...
    99+
    2023-06-29
  • ThreadLocal的set方法原理是什么
    这篇文章主要介绍了ThreadLocal的set方法原理是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇ThreadLocal的set方法原理是什么文章都会有所收获,下面我们一起来看看吧。前沿知识Threa...
    99+
    2023-07-05
  • 什么是ThreadLocal
    这期内容当中小编将会给大家带来有关什么是ThreadLocal,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。一 引言ThreadLocal的官方API解释为:* ...
    99+
    2024-04-02
  • ThreadLocal工作原理及用法是什么
    今天就跟大家聊聊有关ThreadLocal工作原理及用法是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。ThreadLocal是什么ThreadLocal是线程Thread中属性...
    99+
    2023-06-22
  • Java中ThreadLocal的用法和原理是什么
    这篇文章主要介绍“Java中ThreadLocal的用法和原理是什么”,在日常操作中,相信很多人在Java中ThreadLocal的用法和原理是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中Th...
    99+
    2023-07-06
  • ThreadLocal的原理和使用场景是什么
    ThreadLocal是Java中的一个类,用于在多线程环境中实现线程内部的数据共享。它提供了一个线程局部变量,每个线程都可以独立地...
    99+
    2023-09-12
    ThreadLocal
  • java中ThreadLocal是什么
    ThreadLocal是JDK包提供的,称为线程本地变量,它将变量与线程绑定在一起,为每一个线程维护一个独立的变量副本,通过ThreadLocal可以将对象的可见范围限制在同一个线程内,从而避免了线程安全问题,对解决多线程程序的并发问题有一...
    99+
    2024-04-02
  • Java中ThreadLocal的原理是什么及怎么使用
    这篇文章主要介绍“Java中ThreadLocal的原理是什么及怎么使用”,在日常操作中,相信很多人在Java中ThreadLocal的原理是什么及怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Jav...
    99+
    2023-07-06
  • python中ThreadLocal的作用是什么
    这篇文章主要介绍“python中ThreadLocal的作用是什么”,在日常操作中,相信很多人在python中ThreadLocal的作用是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”python中Th...
    99+
    2023-07-05
  • Spring中使用自定义ThreadLocal存储导致的坑及解决方法是什么
    本篇文章为大家展示了Spring中使用自定义ThreadLocal存储导致的坑及解决方法是什么,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Spring自定义ThreadLocal存储导致的坑Spr...
    99+
    2023-06-21
  • ThreadLocal三大坑是什么
    本篇内容主要讲解“ThreadLocal三大坑是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“ThreadLocal三大坑是什么”吧!内存泄露由于ThreadLocal的key是弱引用,因此...
    99+
    2023-06-15
  • java中的ThreadLocal是什么
    这篇文章将为大家详细讲解有关java中的ThreadLocal是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。简单介绍ThreadLocal一般称为线程本地变量,它是一种特殊的线程绑定机制,将变量与线...
    99+
    2023-06-19
  • SQLT使用方法是什么
    本篇内容主要讲解“SQLT使用方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SQLT使用方法是什么”吧!主要方法在使用 SQLT ...
    99+
    2024-04-02
  • ChatGPT使用方法是什么
    本文小编为大家详细介绍“ChatGPT使用方法是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“ChatGPT使用方法是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。具体...
    99+
    2023-02-22
    chatgpt
  • vuex使用方法是什么
    这篇文章主要介绍“vuex使用方法是什么”,在日常操作中,相信很多人在vuex使用方法是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”vuex使用方法是什么”的疑惑有所帮助!接下来,请跟着小编一起来学习吧...
    99+
    2023-07-04
  • minidwep使用方法是什么
    Minidwep是一种无线网络密码破解工具,可以用于破解无线网络密码。以下是使用Minidwep的步骤:1. 下载和安装Minidw...
    99+
    2023-09-16
    minidwep
  • Quartz.Net使用方法是什么
    本篇内容主要讲解“Quartz.Net使用方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Quartz.Net使用方法是什么”吧!在项目的开发过程中,难免会遇见后需要后台处理的任务,例如...
    99+
    2023-06-22
  • ADO.Net Sql使用方法是什么
    这篇文章主要讲解了“ADO.Net Sql使用方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“ADO.Net Sql使用方法是什么”吧!System.Data.SqlClient n...
    99+
    2023-06-17
  • saltstack的使用方法是什么
    SaltStack是一个基于Python的开源自动化和配置管理工具,它使用一个称为Salt的远程执行框架来执行命令和配置任务。 要使...
    99+
    2024-03-06
    saltstack
  • sphinx的使用方法是什么
    Sphinx是一个用于生成文档的工具,特别适用于编写技术文档和API文档。 以下是使用Sphinx的基本步骤: 安装Sphinx:...
    99+
    2023-10-24
    sphinx
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作