系列二、为什么要使用ThreadLocal?

news2024/9/20 18:36:23

一、为什么要使用ThreadLocal?

1.1、概述

        并发场景下,会存在多个线程同时修改一个共享变量的场景,这就有可能会出现线程安全的问题。为了解决线程安全问题,可以用加锁的方式,比如对核心代码使用synchronized或者Lock进行加锁,从而起到线程隔离的效果。但是加锁的方式,在高并发下会导致系统变慢,加锁示意图如下:

        还有另外一种方案,就是使用空间换时间的方式,即:使用ThreadLocal,使用ThreadLocal访问共享变量时,会在每个线程本地保存一份共享变量的副本。多线程对共享变量修改时,实际上每个线程操作的是自己的变量副本,从而保证线程安全。示意图如下:

1.2、线程不安全案例

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/21 11:50
 * @Description: 需求:线程隔离(线程不安全案例代码)
 */
public class SetAndGetThreadVariableDemo1MainApp {
    /**
     * 共享变量
     */
    private String content;
    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public static void main(String[] args) {
        SetAndGetThreadVariableDemo1MainApp app = new SetAndGetThreadVariableDemo1MainApp();
        for (int i = 1; i <= 5; i++) {
            new Thread(() -> {
                try {
                    app.setContent(Thread.currentThread().getName() + "的数据");
                    System.out.println("=======================");
                    System.out.println(Thread.currentThread().getName() + "===>" + app.getContent());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }, "线程" + i).start();
        }
    }

}

1.3、线程不安全案例(ThreadLocal解决)

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/21 11:50
 * @Description: 需求:线程隔离(ThreadLocal实现)
 * 在多线程并发的场景下,每个线程中的变量都是互相独立的
 *      线程A:    设置(变量1)     获取(变量1)
 *      线程B:    设置(变量2)     获取(变量2)
 *
 * ThreadLocal:
 *      1、set():将变量绑定到当前线程中
 *      2、get():获取当前线程绑定的变量
 */
public class SetAndGetThreadVariableDemo2MainApp {

    private String content;
    ThreadLocal<String> threadLocal = new ThreadLocal<>();

    public String getContent() {
        return threadLocal.get();
    }

    public void setContent(String content) {
        threadLocal.set(content);
    }

    public static void main(String[] args) {
        SetAndGetThreadVariableDemo2MainApp app = new SetAndGetThreadVariableDemo2MainApp();
        for (int i = 1; i <= 5; i++) {
            new Thread(() -> {
                try {
                    app.setContent(Thread.currentThread().getName() + "的数据");
                    System.out.println("=======================");
                    System.out.println(Thread.currentThread().getName() + "===>" + app.getContent());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }, "线程" + i).start();
        }
    }

}

1.4、线程不安全案例(synchronized解决)

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/21 11:50
 * @Description: 需求:线程隔离(synchronized实现)
 *
 */
public class SetAndGetThreadVariableDemo3MainApp {

    private String content;

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public static void main(String[] args) {
        SetAndGetThreadVariableDemo3MainApp app = new SetAndGetThreadVariableDemo3MainApp();
        for (int i = 1; i <= 5; i++) {
            new Thread(() -> {
                try {
                    synchronized (SetAndGetThreadVariableDemo3MainApp.class) {
                        app.setContent(Thread.currentThread().getName() + "的数据");
                        System.out.println("=======================");
                        System.out.println(Thread.currentThread().getName() + "===>" + app.getContent());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }, "线程" + i).start();
        }
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1271669.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker的基本概念和优势,以及实际应用场景

目录 概要 基本概念 容器 (Container) 什么是容器 容器与虚拟机的区别 镜像 (Image) Dockerfile 仓库 (Repository) 容器编排 (Orchestration) Docker Compose Docker Daemon 和 Docker Client 网络 (Network) 数据卷 (Volume) 主要优势 提高移植性和可移植性 提…

基于Java SSM框架+Vue实现垃圾分类网站系统项目【项目源码+论文说明】

基于java的SSM框架Vue实现垃圾分类网站系统演示 摘要 本论文主要论述了如何使用JAVA语言开发一个垃圾分类网站 &#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述…

【EI会议征稿通知】第七届结构工程与工业建筑国际学术会议(ICSEIA 2024)

第七届结构工程与工业建筑国际学术会议&#xff08;ICSEIA 2024&#xff09; 2024 7th International Conference on Structural Engineering and Industrial Architecture 随着城市化进程的不断深入&#xff0c;建筑领域的需求也在优化、调整。结构工程的发展依旧受到重视&am…

centos7 nginx_keepalived 在主备服务器上安装

脚本地址 https://gitcode.net/zengliguang/nginx_keepalived.git 文件说明keepalivedkeepalived的离线安装包nginx-1.24.0nginx的离线安装包centos7_keepalived_offline_install_backup.shkeepalved安装脚本&#xff0c;备服务器安装 centos7_keepalived_offline_install_mas…

实验8配置工具

一、实验目的 1. 掌握UML中建模工具——部署图&#xff0c;用于显示系统中软件和硬件的物理架构。 2. 掌握应用Visio等业界常用的建模工具的基本使用方法和基本绘图操作&#xff0c;选择一种并熟练使用&#xff0c;会使用该工具针对具体问题建立分析模型。 二、实验内容与步骤…

ESP32-Web-Server编程- 使用SSE 实时更新设备信息

ESP32-Web-Server编程- 使用SSE 实时更新设备信息 概述 如前所述&#xff0c;传统 HTTP 通信协议基于 Request-Apply&#xff08;请求-响应&#xff09;机制&#xff0c;浏览器&#xff08;客户端&#xff09;只能单向地向服务器发起请求&#xff0c;服务器无法主动向浏览器推…

C语言——指针(三)

&#x1f4dd;前言&#xff1a; 上篇文章C语言——指针&#xff08;二&#xff09;中对&#xff1a;指针的运算和指针变量类型对指针使用的影响开展了进一步的探讨&#xff0c;这篇文章我们继续学习一下指针与一维数组之间的关系&#xff1a; 1&#xff0c;对数组名的理解 2&am…

什么是网络可视化?网络可视化工具有用吗

网络可视化定义是自我描述的&#xff0c;因为它在单个屏幕上重新创建网络布局&#xff0c;以图形和图表的形式显示有关网络设备、网络指标和数据流的信息&#xff0c;为 IT 运营团队提供一目了然的理解和决策。 网络是复杂的实体&#xff0c;倾向于持续进化&#xff0c;随着业…

关于pyqt5与moviepy到打包的坑点

1,pyqt5 关于pyqt5 designer.exe 的使用主要就是了解pyqt5右侧菜单栏的功能使用 打包后的文件&#xff0c;需要继承改类&#xff0c;进行图形指令交互 关于pyqt5&#xff0c;要了解信号&#xff0c;和槽点的相互关系。 我在pyqt5中使用moviepy的时候&#xff0c;需要用到异步…

css 字体倾斜

css 字体倾斜 //左右倾斜 transform: skew(40deg, 0deg);//上下倾斜 transform: skew(0deg, 16deg);

服务器安装JDK17 版本显示JDK8

服务器之前安装的是JDK8&#xff0c;后面升级JDK17后&#xff0c;发现执行 java -vsrsion 显示的是此时我的环境变量已经换成了JAVA17的路径 输入&#xff1a; vim /etc/profile 解决办法&#xff1a; 1.更新自己环境变量 bash export JAVA_HOME/usr/local/jdk-17.0.7 …

6种可改善软件的可用性测试方法

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

关于项目时间与数据库中的时间不一致问题(少8个小时)

关于项目情况: 1.springboot项目 2.数据库为MySQL 3.数据库时间正常,与实际时间一致. 4.项目获取到的时间比数据库的时间少八个小时 原因是没有给日期格式设置时区,导致其变为世界时,比北京时间少八个小时 在application.yml 配置文件中添加时区属性; 配置文件路径 spri…

电商干货:怎么从客服的角度降低退款率?

【售前阶段】 订单状态为[买家已付款](未发货) →选择原因:价格贵 建议处理方式:客服主动和买家说明产品 有哪些功能优势、店铺有哪些服务优势(如10年质保免费以日换新、运费险、7/15天无理由、30天保价等) 注意事项: 注重回复的话术。看挽单话术是否需要优化。是否太过于…

【ESP32】手势识别实现笔记:红外温度阵列 | 双三次插值 | 神经网络 | TensorFlow | ESP-DL

目录 一、开发环境搭建与新建工程模板1.1、开发环境搭建与卸载1.2、新建工程目录1.3、自定义组件 二、驱动移植与应用开发2.1、I2C驱动移植与AMG8833应用开发2.2、SPI驱动移植与LCD应用开发2.3、绘制温度云图2.4、启用PSRAM&#xff08;可选&#xff09;2.5、画面动静和距离检测…

eBay需要添加什么卡可以付费?

前言 最近很多朋友不管是做eBay易贝卖家还是在eBay海淘下单购物的都或多或少遇到无法用卡付费的问题&#xff0c;甚至很多朋友之前明明可以用卡去付费&#xff0c;第一次可以第二次却不行了&#xff0c;想不到吧&#xff1f;这eBay平台还有这种骚操作&#xff0c;那到底用什么…

ssm的鲜花销售系统(有报告)。Javaee项目。

演示视频&#xff1a; ssm的鲜花销售系统&#xff08;有报告&#xff09;。Javaee项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring SpringMvc Mybatis…

内网穿透的应用-如何部署Tale博客并结合cpolar内网穿透发布个人站点到公网访问

Linux系统部署Tale个人博客并发布到公网访问 文章目录 Linux系统部署Tale个人博客并发布到公网访问前言1. Tale网站搭建1.1 检查本地环境1.2 部署Tale个人博客系统1.3 启动Tale服务1.4 访问博客地址 2. Linux安装Cpolar内网穿透3. 创建Tale博客公网地址4. 使用公网地址访问Tale…

SSM6 11-27 SpringMvc过滤器和异常处理

try catch:处理异常 throw/throws:不处理 抛出 jvm中断程序运行 打印错误信息 web:经典三层模型&#xff1a; dao(mapper) service web层 异常抛给web层Controller类的方法&#xff0c;每个方法可能处理异常,可能处理异常代码相似,造成重复代码重复编写 web层再往上抛 …

初识Java 18-6 泛型

目录 潜在类型机制 支持潜在类型机制的语言 Python的潜在类型机制 C的潜在类型机制 Java中的直接潜在类型机制 潜在类型机制的替代方案 反射 将方法应用于序列中的每个元素 Java 8的潜在类型机制&#xff08;间接实现&#xff09; 潜在类型机制的使用例&#xff08;S…