【Java】使用外部变量初始化子线程 上

如何在lambda内部修改外部局部变量的值/如何用lambda重构for循环计数 Talk is cheap, show me your code! 看一段代码: /** * 在lambda表达式内部,修改lambda表达式外部的局部变量的值 */ private synchronized void updateLocalVariable() { List<String> list = new ArrayList<>(); ... 阅读详情

问题

如何使用外部变量初始化子线程

来源

写C#的时候发现的问题,现在用Java来说明一下(为什么用Java?)。通常在创建子线程的时候需要向子线程引入一些外部变量来进行初始化,这时候可以使用2种方式来通过编译(仅仅通过编译而已),那么哪种方法才是正确的呢?

代码

import java.util.Calendar;
import java.util.Random;

public class Main {

    int tInt;

    String tString;

    final int Test_Cnt = 10;

    public static void main(String[] args) {

        // new Main().threadTestA();

        // new Main().threadTestB();

        // new Main().threadTestC();

        // new Main().threadTestD();

        // new Main().threadTestE();
    }

    public void threadTestA() {

        Thread[] threads = new Thread[Test_Cnt];

        for(int i = 0; i < Test_Cnt; ++i) {

            tString = String.format("thread %d", i); // (1)

            threads[i] = new Thread() {

                @Override
                public void run()
                {
                    Random r = new Random(Calendar.getInstance().getTimeInMillis());

                    try { Thread.sleep(1000 + r.nextInt(2000)); } catch (InterruptedException e) {  }

                    System.out.println(tString);
                }
            };
        }

        for(Thread thr : threads) thr.start();

        for(Thread thr : threads) try { thr.join(); } catch (InterruptedException e) { }
    }

    public void threadTestB() {

        Thread[] threads = new Thread[Test_Cnt];

        for(int i = 0; i < Test_Cnt; ++i) {

            tInt = i; // (2)

            threads[i] = new Thread() {

                @Override
                public void run()
                {
                    Random r = new Random(Calendar.getInstance().getTimeInMillis());

                    try { Thread.sleep(1000 + r.nextInt(2000)); } catch (InterruptedException e) {  }

                    System.out.println(tInt);
                }
            };
        }

        for(Thread thr : threads) thr.start();

        for(Thread thr : threads) try { thr.join(); } catch (InterruptedException e) { }
    }

    public void threadTestC() {

        Thread[] threads = new Thread[Test_Cnt];

        for(int i = 0; i < Test_Cnt; ++i) {

            final String ftString = String.format("thread %d", i); // (3)

            threads[i] = new Thread() {

                @Override
                public void run()
                {
                    Random r = new Random(Calendar.getInstance().getTimeInMillis());

                    try { Thread.sleep(1000 + r.nextInt(2000)); } catch (InterruptedException e) {  }

                    System.out.println(ftString);
                }
            };
        }

        for(Thread thr : threads) thr.start();

        for(Thread thr : threads) try { thr.join(); } catch (InterruptedException e) { }
    }

    public void threadTestD() {

        Thread[] threads = new Thread[Test_Cnt];

        for(int i = 0; i < Test_Cnt; ++i) {

            final int itInt = i; // (4)

            threads[i] = new Thread() {

                @Override
                public void run()
                {
                    Random r = new Random(Calendar.getInstance().getTimeInMillis());

                    try { Thread.sleep(1000 + r.nextInt(2000)); } catch (InterruptedException e) {  }

                    System.out.println(itInt);
                }
            };
        }

        for(Thread thr : threads) thr.start();

        for(Thread thr : threads) try { thr.join(); } catch (InterruptedException e) { }
    }

    public void threadTestE() {

        Thread[] threads = new Thread[Test_Cnt];

        for(int i = 0; i < Test_Cnt; ++i) {

            tInt = i; // (5)

            threads[i] = new Thread() {

                @Override
                public void run()
                {
                    int rInt = tInt; // (5)

                    Random r = new Random(Calendar.getInstance().getTimeInMillis());

                    try { Thread.sleep(1000 + r.nextInt(2000)); } catch (InterruptedException e) {  }

                    System.out.println(rInt);
                }
            };
        }

        for(Thread thr : threads) thr.start();

        for(Thread thr : threads) try { thr.join(); } catch (InterruptedException e) { }
    }
}

说明

主要区别使用 // (num) 形式表明了。选用 String 和 int 是为了验证值类型和引用类型的区别。

结果表明 threadTestA 和 threadTestB 都不能正确执行,更具体的说它们输出的数字都是9。因为这10个线程并没有在定义时获得变量 i 的值,它们被要求在需要该值时向外部的成员变量 sInt 和 sString 取值,而在生成线程的循环中这2个变量就已经被修改的面目全非了(poi~了相了),当这10个线程开始执行的时候,自然获取到的是sInt 和 sString 在最后的修改中保留下的值。

而 threadTestC 和 threadTestD 可以如期运行。因为 final 的约束,局部变量被赋值后即不可修改,从而保证了各子线程在取值时能够取到其上下文中定义的值(按理说局部变量应该分配在栈中,但是我感觉这种被 final 修饰的局部变量应该被分配到了堆里,当然我目前没能力证明囧~) ,看上去和闭包有点像了,毕竟内部类依赖外部类中的局部变量,从而延长了外部类局部变量的生命周期。

threadThreadE 也不能正确执行,脑抽的时候写的,没什么参考价值。

总结

所以说需要使用外部变量初始化子线程的时候需要使用 final 进行修饰,当然语法已经这么限制了(对于局部变量),而且这个语法针对的(不是某个类 我是说Java的各种类都是辣鸡 大雾)是内部类,而不是单独为线程服务。使用外部成员变量的时候务必小心上文中的那种方式,很可能会产生N个一样的子线程。当然如果只生成1个子线程,那么这2种方法都没有问题,需要考虑的只有主线程和子线程对成员变量的竞争而已。

父线程变量需要传递到子线程使用一种方式InheritableThreadLocal和TransmittableThreadLocal 前言 ThreadLocal是相对于每一个线程自己使用的本地变量,有这样的一种需求:父线程生成的变量需要传递到子线程中进行使用。需要使用新的InheritableThreadLocal类来实现,但 InheritableThreadLocal的使用利用Thread 的初始化。我们经常在使用线程的时候,都是使用线程池的方式这个时候就需要TransmittableThreadLocal登场来解决。 实践 一、InheritableThreadLocal使用 public class LocalThreadUti 阅读详情

相关推荐

2025海外代理IP深度横评:Bright Data、IPFoxy、SmartProxy等六大服务商实战对比

本文深度横评2025年六大海外代理IP服务商(Bright Data、IPFoxy、SmartProxy、IPIPGO、Kookeey及青果网络),基于实战测试数据,从IP池质量、速度稳定性、性价比等维度进行对比。针对跨境电商、数据爬虫、社交媒体管理等不同业务场景,提供精准的选购指南与避坑建议,帮助企业用户根据自身需求选择最合适的代理IP解决方案。

weixin_29196891的博客 434

Java多线程之间通信——修改对象中的成员变量

线程之间的通信,可通过对对象的成员变量的状态修改,达到控制线程的目的。 Java中,线程要基于对象才能创建。如: ThreadTest t1 = new ThreadTest(); t1.start();//启动一个线程,并运行ThreadTest 中的run()方法 如何对另外一个线程的状态控制,通过传入另外那个对象的实例,然后调用另外这个对象的私有函数,该私有函数内改变成员变量的状态。

1080

图形学基础知识:着色(三)Rendering Pipeline与Shader

管线(Pipeline) 什么是管线? 管线我们可以理解为流水线,流水线大家都懂,就是工厂里面生产东西的一整套流程。例如饮料厂要生产饮料,需要洗瓶子,倒饮料,加盖,包装等等,这一整套过程就是流水线。那么我们要把一个三维场景渲染成一幅二维的图像,同样需要一个先干嘛再干嘛然后干嘛最后干嘛的过程,这个过程或流水线,我们就称之为管线。 实时渲染管线(Real-time Rendering Pipeline) 通过前面几篇的学习,我们知道了要把一个三维场景渲染成一幅二维的图像大致分为以下几个步骤: M.

王王王渣渣的博客 2532

JAVA多线程中访问变量问题

类变量(类里面static修饰的变量)保存在“方法区”实例变量(类里面的普通变量)保存在“堆”局部变量(方法里声明的变量)“虚拟机栈” “方法区”和“堆”都属于线程共享数据区,“虚拟机栈”属于线程私有数据区。 因此,局部变量是不能多个线程共享的,而类变量和实例变量是可以多个线程共享的。事实上,在java中,多线程间进行通信的唯一途径就是通过类变量和实例变量。也就是说

哦绝影 7359

南方cass9.1【Frame主框架程序没有加载】解决方法(附安装包)

南方cass9.1【Frame主框架程序没有加载】解决方法。

weixin_46066938的博客 3万+

全球APN信息汇总

全球APN信息,电信APN,移动APN,联通APN,台湾APN,马来西亚APN,俄罗斯APN,日本APN,泰国APN,美国APN,英国APN,法国APN,德国APN,意大利APN,葡萄牙APN,土耳其APN,荷兰APN,丹麦APN,比利时APN,爱尔兰APN,新加坡APN,越南APN,老挝APN,菲律宾APN,印尼APN,泰国APN,柬埔寨APN,巴基斯坦APN,印度APN,奥地利APN,保加利亚APN,捷克APN,立陶宛APN,罗马尼亚APN,挪威APN,希腊APN,匈牙利APN,瑞士APN,乌克兰APN

renkai721的专栏 2796

【Java】使用外部变量初始化子线程 下

使用外部变量初始化子线程的一些具体的技巧

古明地觉<如是说>:: 438

R语言Dunnett’s检验实战:寻找差异组之间的效果

总结起来,本文以R语言为工具,演示了如何使用Dunnett’s检验来找出单因素方差分析中不同组之间的效果差异。在本篇文章中,我们将通过R语言实战演示如何使用Dunnett’s检验来寻找不同组之间的效果差异。在分析结果时,通常我们会关注具有显著差异的组别,并基于Dunnett’s检验结果进行进一步的解释和讨论。首先,我们需要准备一组数据,假设我们有一个实验,涉及到四个不同的处理组和一个对照组。当我们发现方差分析结果显示存在显著差异时,我们可以进一步进行Dunnett’s检验来确定具体哪些组之间存在差异。

CoderExtra的博客 1104

InheritableThreadLocal——父线程传递本地变量到子线程的解决方式及分析

上一个博客提到ThreadLocal变量的基本使用方式,可以看出ThreadLocal是相对于每一个线程自己使用的本地变量,但是在实际的开发中,有这样的一种需求:父线程生成的变量需要传递到子线程中进行使用,那么在使用ThreadLocal似乎就解决不了这个问题,难道这个业务就没办法使用这个本地变量了吗?答案肯定是否定的,ThreadLocal有一个子类InheritableThreadLo...

代码小司机 5万+

Windows 下 OpenClaw(小龙虾) 安装全记录:从零到一的保姆级图文教程(持续更新中)

本文主要介绍了Windows 下 OpenClaw 安装全记录:从零到一的保姆级图文教程,希望能对学习使用OpenClaw 的同学们有所帮助。 文章目录 1. 背景 2. 实战教程 2.1 步骤一 安装Node.js 2.2 步骤二:安装并配置OpenClaw 2.3 步骤三:配置模型 2.4 步骤四:对话 3. 后续使用步骤

weixin_43178406的博客 16万+

《用 Python 爬取统计局年鉴:从 API 抓取到结构化分析,实战全流程详解》

在数据分析、经济研究、商业决策中,国家统计局发布的年鉴数据具有权威性和参考价值。本篇博客将带你从零实践:了解目标、设计爬虫、抓取年度数据、解析 JSON、保存结构化数据、并用 Pandas 简要分析可视化,且使用现代 Python 最佳实践(如httpx、pydantic、typer 等),提升代码质量与效率。如何抓取国家统计局年鉴数据;利用 API 方式高效获取;使用现代异步 Python 提升性能;将数据结构化输出;结合 CLI、类型校验和简单分析技术提升实用性。

2201_76125261的博客 1085

【Java】子线程获取父线程ThreadLocal

阅读这篇博客前,请确保你对ThreadLocal的使用场景和实现原理有一定了解。【Java】ThreadLocal原理与使用场景-优快云博客。本文主要聚焦于ThreadLocal在父子线程间传递的原理。

Annancqxxx的博客 2465

ansys license许可证问题:Ansys License Manager Release 2024 R1...如何解决?

🏆本文收录于 《全栈 Bug 调优(实战版)》 专栏。专栏聚焦真实项目中的各类疑难 Bug,从成因剖析 → 排查路径 → 解决方案 → 预防优化全链路拆解,形成一套可复用、可沉淀的实战知识体系。无论你是初入职场的开发者,还是负责复杂项目的资深工程师,都可以在这里构建一套属于自己的「问题诊断与性能调优」方法论,助你稳步进阶、放大技术价值 。

**My Coding Family** 5368

ThreadLocal 如何实现父子线程共享变量?

Java实现父子线程共享ThreadLocal变量的3种方案:1)推荐使用JDK原生的InheritableThreadLocal,通过子线程初始化时复制父线程数据实现共享,但线程池复用会失效;2)基础方案通过构造函数手动传递变量,适用于简单非线程池场景;3)阿里开源的TransmittableThreadLocal可解决线程池复用问题,通过包装任务实现动态传递。方案选择需根据是否使用线程池、变量共享范围等需求决定,同时要注意内存泄漏和对象引用共享问题。

weixin_42449750的博客 1050

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

java内部类引用外部变量

今天学习AQS时,发现在main方法中实例一个ReentrantLock,在线程内部类能够直接使用,当时就很奇怪,因为按照自己的理解,想要使用外部的变量,一般都是通过类的方法传递。 后来查了下资料,方法中的内部类是可以直接使用外部变量的。 但是有个前提就是该变量必须是final或者effectively final的。 effectively final就是指变量初始化后没有被更改。 对于基础数据类型,就是值不能被更改。 对于引用类型,就是指向不能更改。 也就是说我们可以在内部类直接使用lock,但是不能更

codecuter的博客 2608

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Java子线程如何传递ThreadLocal的值?

在Java中,ThreadLocal为每个线程提供独立的变量副本,默认情况下子线程无法直接继承父线程的ThreadLocal值。若需实现父子线程间的值传递,可通过以下方式:1. 显式传递:父线程通过ThreadLocal.get()获取值,并在子线程中通过ThreadLocal.set()设置该值。2. initialValue()方法:在子线程创建时,通过initialValue()方法重新初始化ThreadLocal值。3. InheritableThreadLocal:使用InheritableThr

weixin_46072507的博客 750

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

子线程如何获取父线程ThreadLocal的值?

Java中如果子线程要获取到父线程中 ThreadLocal 中的值,需要使用其子类InheritableThreadLocal 实现。 测试代码如下: public class Get_ThreadLocal { public static void main(String[] args) throws InterruptedException { Thread parentParent = new Thread(() -> { ...

Android系统优化 4408

InheritableThreadLocal源码解析,子线程如何获取父线程的本地变量?

日常工作中,经常使用`ThreadLocal`来避免线程并发问题,每个线程访问自己本地的变量,没有竞争,没有锁,非常高效。现在有一个业务场景,需要创建一些子线程来执行任务,主线程中设置了`ThreadLocal`的值,想在子线程中获取,能获取到吗?答案是:不能。

你学废了吗? 950

Java获取父线程信息_Java中父线程和子线程之间的通信 - java

我有一个主线程,并且在该线程中启动了一个新线程。 (子线程)。该子线程将打开服务器套接字,并开始侦听连接。我希望该线程停止执行,并在主线程从外部获取消息(从何处获取消息不是问题)时关闭其初始化的所有内容(如Socket)。我要如何停止线程并关闭所有连接。我应该使用共享变量吗?这样,当主线程接收到该消息时,它应该对其进行修改,而子线程应该继续检查该共享变量中的更改?我应该如何实施?一些有用的链接可能...

weixin_33389310的博客 745

子线程无法访问父线程中通过ThreadLocal设置的变量

ThreadLocal变量无法在子线程中访问父线程设置的值,因为ThreadLocal的数据存储在与当前线程绑定的ThreadLocalMap中。当创建新线程时,子线程拥有独立的ThreadLocalMap,因此无法获取父线程设置的值。InheritableThreadLocal可以解决这个问题,它允许子线程继承父线程的ThreadLocal值。由于不同线程拥有独立的threadLocals,所以ThreadLocal实现了线程隔离。

沐雨橙风ιε的博客 468

如何让子线程获取到父线程的ThreadLocal中的值

代码demo如下: public static void main(String[] args) throws InterruptedException { Thread parentParent = new Thread(new Runnable() { @Override public void run() { ThreadLocal threadLocal = new ThreadLocal(); threadLo

硅脂味咖啡的博客 2904

C语言线程本地变量 原理,ThreadLocal解析:父线程的本地变量不能传递到子线程详解...

众所周知,ThreadLocal类是java提供线程本地变量的工具类。但父线程的本地变量却不能被子线程使用,代码如下:public static void main(String[] args) {ThreadLocal threadLocal = new ThreadLocal<>();threadLocal.set("abc");System.out.println("父线程:"+...

weixin_42636895的博客 847

ThreadLocal父子线程传递问题

优雅的实现父子线程的数据传递

SunHongmin 2928
上一篇: 【OneNote】插入语法高亮的代码
下一篇: 【Java】使用外部变量初始化子线程 下
古明地觉
博客等级 码龄15年 2粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值