ThreadLocal 在上下文传值场景实践源码

yizhihongxing

ThreadLocal 是 Java 中常用的多线程编程技术之一,它可以在多个线程环境中保存并传递数据,将数据与线程绑定在一起,实现线程的局部变量。在一些上下文传值的场景中,ThreadLocal 可以较为方便的实现参数的传递。接下来,本文将详细讲解 ThreadLocal 在上下文传值场景实践源码的完整攻略。

什么是 ThreadLocal

ThreadLocal 是一个与线程绑定的变量,它可以在不同线程中保存和取出相应的值,即每个 ThreadLocal 对象都可以在某个线程中存储一个值。在多个线程环境下,每个线程可能都需要访问变量并进行修改,但是线程之间互相干扰会导致数据不一致,ThreadLocal 就是为了解决这一问题而存在的。

在 Java 中,ThreadLocal 可以实现变量的线程局部化,保证每个线程中有自己的变量副本,避免线程干扰,实现了线程间数据的隔离。ThreadLocal 常用于应用中跨越多个组件、层或方法的上下文传值场景中,就可以避免传参的烦扰。单例线程池异步处理的时候,经常需要在线程调用之前或结束时传递一些值。

ThreadLocal 用法示例

下面让我们通过两个示例来说明 ThreadLocal 的用法,先定义一个简单的 Request 类,模拟一个请求。

public class Request {

    private final String name;

    public Request(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

示例一:通过 ThreadLocal 将 Request 对象在多个方法中传递

假设现在有一个三层的方法嵌套:firstMethod -> secondMethod -> thirdMethod,需要将一个 Request 对象在这三个方法中传递。此时可以使用 ThreadLocal,将 Request 对象绑定到当前线程中。

public class ThreadLocalExample1 {

    private static final ThreadLocal<Request> REQUEST_THREAD_LOCAL = new ThreadLocal<>();

    public static void main(String[] args) {
        Request request = new Request("test");
        REQUEST_THREAD_LOCAL.set(request);
        firstMethod();
    }

    public static void firstMethod() {
        Request request = REQUEST_THREAD_LOCAL.get();
        System.out.println("firstMethod get request: " + request.getName());
        secondMethod();
    }

    public static void secondMethod() {
        Request request = REQUEST_THREAD_LOCAL.get();
        System.out.println("secondMethod get request: " + request.getName());
        thirdMethod();
    }

    public static void thirdMethod() {
        Request request = REQUEST_THREAD_LOCAL.get();
        System.out.println("thirdMethod get request: " + request.getName());
    }
}

运行结果如下:

firstMethod get request: test
secondMethod get request: test
thirdMethod get request: test

从结果可以看出,通过 ThreadLocal 可以实现变量在多个方法中的传递,非常方便。

示例二:在多线程环境中使用 ThreadLocal

假如现在有 2 个线程,需要对一个计数器进行操作,每个线程自己维护计数。此时可以使用 ThreadLocal,将计数器的值绑定到当前线程中。

public class ThreadLocalExample2 {

    private static final ThreadLocal<Integer> COUNTER = new ThreadLocal<Integer>() {
        @Override
        protected Integer initialValue() {
            return 0;
        }
    };

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            int counter = COUNTER.get();
            for (int i = 0; i < 5; i++) {
                counter++;
                COUNTER.set(counter);
                System.out.println(Thread.currentThread().getName() + " - " + counter);
            }
        });

        Thread t2 = new Thread(() -> {
            int counter = COUNTER.get();
            for (int i = 0; i < 5; i++) {
                counter++;
                COUNTER.set(counter);
                System.out.println(Thread.currentThread().getName() + " - " + counter);
            }
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }
}

运行结果如下:

Thread-0 - 1
Thread-0 - 2
Thread-0 - 3
Thread-0 - 4
Thread-0 - 5
Thread-1 - 1
Thread-1 - 2
Thread-1 - 3
Thread-1 - 4
Thread-1 - 5

从结果可以看出,每个线程自己维护自己的计数器,ThreadLocal 实现了在多线程环境下的计数器对象的隔离。

结语

本文详细讲解了 ThreadLocal 在上下文传值场景实践源码的完整攻略,并提供了两个示例,希望可以帮助到大家。ThreadLocal 是一个非常实用的多线程编程技术,可以帮助避免线程干扰的问题,实现线程间数据隔离。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:ThreadLocal 在上下文传值场景实践源码 - Python技术站

(0)
上一篇 2023年6月7日
下一篇 2023年6月7日

相关文章

  • WinForm调用jar包的方法分析

    WinForm是一种Windows桌面应用程序开发框架,而Java的jar包是一种Java程序打包方式。在WinForm应用程序中,我们可能需要调用Java的jar包来实现某些功能。本文将提供详解“WinForm调用jar包的方法分析”的完整攻略,包括如何将Java的jar包添加到WinForm项目中、如何在WinForm中调用Java的jar包等。 将Ja…

    C# 2023年5月15日
    00
  • C#实现读取txt文件生成Word文档

    下面是”C#实现读取txt文件生成Word文档”的完整攻略: 1. 背景 在我们的开发过程中,经常需要将txt文本转化为Word文档,但Word文档是二进制格式的文档,不方便手动编辑,这时,我们可以通过C#程序来实现读取txt文件生成Word文档的操作。 2. 准备工作 安装Microsoft Office Word 16.0 Object Library …

    C# 2023年6月1日
    00
  • 使用.NET Core创建exe应用程序

    使用.NET Core创建exe应用程序需要分为以下几步: 步骤1:安装.NET Core SDK 在开始创建应用程序之前,首先需要在本地计算机上安装.NET Core SDK(Software Development Kit)。可以访问 .NET Core SDK官网 根据自己的需要选择合适的.NET Core版本进行下载和安装。 步骤2:创建.NET C…

    C# 2023年6月3日
    00
  • C#删除字符串中重复字符的方法

    以下是“C#删除字符串中重复字符的方法”的完整攻略: 1. 查找字符串中的重复字符 要删除字符串中的重复字符,首先需要查找到字符串中的重复字符。我们可以遍历字符串中的每一个字符,然后与后面的字符逐个比较,如果有重复的字符,则记录其位置。这个过程可以用嵌套的for循环来实现: string str = "hello world"; List…

    C# 2023年6月8日
    00
  • C# 数组实例介绍(图文)

    C# 数组实例介绍(图文)攻略 介绍 本文将介绍C#中数组的概念、语法、类型和常用操作方法,并提供多个示例以帮助读者深入理解。 数组的概念 数组是一组相同类型的变量集合,它们在内存中按照一定顺序被存储和访问。 数组的语法 以下是数组的语法: //声明一个int类型的数组,长度为5 int[] myArray = new int[5]; //直接初始化数组元素…

    C# 2023年5月31日
    00
  • C#程序窗体间使用回调事件方式通讯示例

    首先需要注意的是,C#窗体间的通讯方式有很多种,而使用回调事件方式通讯是其中一种较为常见的方式。实现回调事件通讯,需要了解委托和事件的相关知识。 一、委托和事件 委托(Delegate)是C#中一个非常重要的概念,它可以看做是一个函数指针,可以指向一个或多个方法。而事件(Event)则是使用委托的一种方式,可以通过事件来触发委托执行。 在C#中声明委托,需要…

    C# 2023年6月7日
    00
  • C#实现时间戳的简单方法

    关于“C#实现时间戳的简单方法”,下面是完整的攻略: 什么是时间戳 时间戳是一种表示某个时间点的数字形式。它通常是一个长整型数值,表示某个固定时间点(如1970年1月1日00:00:00)到现在经过的毫秒数或者秒数,是一种比较方便的时间表示方式,被广泛应用于网络通讯和数据存储操作中。 实现时间戳的方法 在C#中,我们可以通过内置的DateTime类来表示日期…

    C# 2023年6月1日
    00
  • C# Path.GetExtension(string path):获取指定路径的文件扩展名

    C#的Path.GetExtension(string path)方法 Path.GetExtension(string path)方法是C#中的一个静态方法,用于获取给定路径(或文件名)的扩展名部分。扩展名是指路径字符串中最后一个点号 . 之后的文本,如果没有点号,则返回空字符串。 例如,对于路径”C:\myfile.txt”,GetExtension方法…

    C# 2023年4月19日
    00
合作推广
合作推广
分享本页
返回顶部