运行打印Hello World启动了多少线程?

news2025/5/28 1:25:30

序言

看网上说阿里二面问到了一个看似最简单且没有标准答案的一个问题,所有学习编程都是从打印hello World开始的,那运行打印启动了多少个线程?

启动了多少线程?

在运行一个简单的 “Hello World” 程序时,启动的线程数量取决于编程语言、运行时环境和操作系统。

就编程语言而言,C语言、C++、Java、Python、Go、JavaScript都是不同的,且最少有一个线程。如果不考虑编程语言的话,就Java语言,有多少个线程也不是确定的。需要看JDK的版本,不同JDK版本启动的线程数量也可能是不同的。

比如下面这个简单的Java程序,怎么看它运行了多少个线程呢?

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}

假设当前电脑JDK版本是Java 8,
在这里插入图片描述

strace命令

方法有很多,如果你是linux环境,使用strace·(system trace是 Linux 系统中一个功能强大的调试、分析、诊断工具,可以对系统调用和信号传递的跟踪结果进行分析)命令进行分析,

  • -c:统计每个系统调用的时间、次数和错误,并在程序退出时报告摘要。
  • -D:将跟踪进程作为分离的孙进程运行,减少strace的可见效果。
  • -d:输出strace关于标准错误的调试信息。
  • -f:跟踪由fork调用所产生的子进程。
  • -t:在输出中的每一行前加上时间信息。
  • -v:输出所有的系统调用,包括环境变量和状态信息。
  • -o:将跟踪结果输出到文件中‌。

在这里插入图片描述
下面的h1就是分析的结果文件,后缀就是对应的线程编号,即下面有很多个线程,less h1.11767可以查看对应的线程内容
在这里插入图片描述
上面代表的是linux操作系统的系统调用日志。

JProfiler工具

JProfiler(Java Profiler)是IDEA自带的Java性能分析工具。左边有几个线程ID,比如线程ID=13571的线程,JavaThread::run() -> CompileBroker::invoke_compiler_on_method(CompileTask*),它是JVM中JIT即时编译器线程,用于在程序运行时将代码转换为机器码。
在这里插入图片描述

下面线程id = 17155的线程,JavaThread::run() -> Compile::Compile(ciEnv*, C2Compiler*, ciMethod*, int, bool, bool, bool),它是进行编译的线程,入参有编译器接口环境指针,C2编译器指针,要编译的方法等参数,
在这里插入图片描述

destroyjavavm线程,它是用于销毁JVM实例的线程,
在这里插入图片描述
Monitor Ctrl-Break监控线程,用于监控控制台中断信号,
在这里插入图片描述
还有Finalizer 线程是一个由 JVM 自动创建的守护线程(Daemon Thread),负责执行对象的 finalize() 方法。它是 Java 垃圾回收(Garbage Collection, GC)机制的一部分。

Thread.getAllStackTraces方法

如下图,该方法获取了所有活动线程的堆栈跟踪信息。

  • Thread[Signal Dispatcher,9,system]=[Ljava.lang.StackTraceElement;@579bb367
  • Thread[main,5,main]=[Ljava.lang.StackTraceElement;@1de0aca6,
  • Thread[Monitor Ctrl-Break,5,main]=[Ljava.lang.StackTraceElement;@255316f2,
  • Thread[Finalizer,8,system]=[Ljava.lang.StackTraceElement;@41906a77,
  • Thread[Reference Handler,10,system]=[Ljava.lang.StackTraceElement;@4b9af9a9
    在这里插入图片描述
    其中Reference Handler线程是Java虚拟机(JVM)中的一个特殊线程,用于处理垃圾回收过程中的对象引用。在Java中,对象引用可能会被垃圾回收器回收,但是如果仍然有其他对象引用这些对象,那么这些对象就不会被回收。Reference Handler线程的作用就是处理这些被引用但不再被使用的对象,以避免内存泄漏。

Reference Handler线程的主要功能是处理四种类型的引用:

  • SoftReference:软引用,只有在内存不足时才会被回收。
  • WeakReference:弱引用,在下一次垃圾回收时会被回收。
  • PhantomReference:虚引用,用于在对象被回收之前执行一些操作。
  • FinalReference:最终引用,用于处理具有finalize方法的对象。

进程、线程和协程的区别

  • 进程‌:系统资源分配的最小单位,每个进程拥有独立的内存空间、文件描述符等资源,进程间完全隔离。
  • 线程‌:运行在进程内部,共享进程的内存空间和文件句柄等资源,但每个线程有自己的栈和局部变量,线程间通过共享资源直接通信。
  • 协程‌:在单线程内通过用户态调度实现并发,不涉及系统资源分配,仅在用户态切换执行流,因此没有独立的内存。

进程(Process)

进程是程序在计算机上运行的一个实例,那一个应用是否是一个进程呢?大多数情况如此,但有些应用中可能包含多个进程,比如VS Code就包含主进程、渲染进程和插件进程。

线程(Thread)

线程是操作系统内核调度的基本单位,线程的创建、销毁、多线程之间的切换都需要操作系统的内核完成。
在这里插入图片描述

协程(Coroutine)

而协程则是利用同一个调度线程去实现协程之间的切换,从而避免了CPU在内核态和用户态之间的来回切换,所以协程的效率比线程要高,比如Go语言天然支持协程,它在协程的帮助下可以轻松实现百万并发。
在这里插入图片描述
那为什么Java一开始就没有用协程的设计呢?原因是由于Java诞生于1995年,多线程模型已经成熟,且被各种操作系统广泛支持。而协程还没有标准化的支持,在不同操作系统上实现方式差距很大,兼容性也不好,所以Java就选择了更加成熟的线程模型。

之后Java在多线程的路上越走越深,为了解决频繁创建和销毁线程导致的性能开销,衍生出了线程池技术。
在这里插入图片描述
但是始终无法解决下面两个问题:

  • 1、线程太多,会导致CPU频繁上下文切换,性能开销大;
  • 2、线程太少,系统吞吐量又不足;

所以衍生出了多线程参数调优:

  • 1、识别适合并行执行的任务;
  • 2、保证线程安全;
  • 3、避免死锁和竞态条件;
  • 4、合理分配核心线程数;
  • 5、优化线程间通信;
  • 6、持续监控和优化;

虚拟线程(Virtual Threads)

JVM)在处理多线程应用时,会使用线程上下文来执行各个线程的任务。然而,在某些情况下,线程上下文可能会成为性能瓶颈。为了解决这个问题,JDK19引入了一项新特性——虚拟线程(Virtual Threads,简称VTs)。虚拟线程是一种在JVM内部实现的并行执行机制,可以提高多线程应用的性能。

与传统的线程相比,虚拟线程具有以下特点:

  1. 无锁竞争:虚拟线程在执行过程中不需要进行锁竞争,这意味着它可以显著降低线程切换的开销,从而提高程序的运行效率。

  2. 无需线程上下文:虚拟线程在执行过程中不需要线程上下文,这意味着它可以更好地利用处理器资源,提高程序的并行执行能力。

  3. 更低的内存开销:虚拟线程的实现方式相对于线程更为轻量级,因此它在内存占用方面具有更小的开销。

看网上的文章是使用@RunOnVirtualThread注解通过AOP去使用虚拟线程,目前开发使用的场景还没有使用过虚拟线程,也不清楚实际的效率提升是多少,需要各位工程师在实践上去测试。

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

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

相关文章

java交易所,多语言,外汇,黄金,区块链,dapp类型的,支持授权,划转,挖矿(源码下载)

目前这套主要是运营交易所类型的,授权的会贵点,编译后的是可以直接跑的,图片也修复了,后门也扫了 都是在跑的项目支持测,全开源 源码下载:https://download.csdn.net/download/m0_66047725/90887047 更多…

(已开源-CVPR2024) RadarDistill---NuScenes数据集Radar检测第一名

本文介绍一篇Radar 3D目标检测模型:RadarDistill。雷达数据固有的噪声和稀疏性给3D目标检测带来了巨大挑战。在本文中,作者提出了一种新的知识蒸馏(KD)方法RadarDistill,它可以通过利用激光雷达数据来提高雷达数据的表征。RadarDistill利用三…

【MySQL】 数据库基础数据类型

一、数据库简介 1.什么是数据库 数据库(Database)是一种用于存储、管理和检索数据的系统化集合。它允许用户以结构化的方式存储大量数据,并通过高效的方式访问和操作这些数据。数据库通常由数据库管理系统(DBMS)管理&…

MongoDB 错误处理与调试完全指南:从入门到精通

在当今数据驱动的世界中,MongoDB 作为最流行的 NoSQL 数据库之一,因其灵活的数据模型和强大的扩展能力而广受开发者喜爱。然而,与任何复杂系统一样,在使用 MongoDB 过程中难免会遇到各种错误和性能问题。本文将全面介绍 MongoDB 的…

【C++】stack,queue和priority_queue(优先级队列)

文章目录 前言一、栈(stack)和队列(queue)的相关接口1.栈的相关接口2.队列的相关接口 二、栈(stack)和队列(queue)的模拟实现1.stack的模拟实现2.queue的模拟实现 三、priority_queu…

ubuntu中上传项目至GitHub仓库教程

一、到github官网注册用户 1.注册用户 地址:https://github.com/ 2.安装Git 打开终端,输入指令git,检查是否已安装Git 如果没有安装就输入指令 sudo apt-get install git 二、上传项目到github 1.创建项目仓库 进入github主页,点击号…

windows 下用yolov5 训练模型 给到opencv 使用

windows 使用yolov5训练模型,之后opencv加载模型进行推理。 一,搭建环境 安装 Anaconda 二,创建虚拟环境并安装yolov5 conda create -n yolov5 python3.9 -y conda activate yolov5 git clone https://github.com/ultralytics/yolov5 cd …

Spark集群架构解析:核心组件与Standalone、YARN模式深度对比(AM,Container,Driver,Executor)

一、核心组件定义与关系拆解 1. ApplicationMaster(AM) 定义:YARN 框架中的应用管理器,每个应用程序(如 Spark 作业)对应一个 AM。职责: 向 YARN 的 ResourceManager 申请资源(Con…

Linux Kernel调试:强大的printk(二)

前言 如果你对printk的基本用法还不熟悉,请先阅读: Linux Kernel调试:强大的printk(一) 上一篇Linux Kernel调试:强大的printk(一)我们介绍了printk的基础知识和基本用法&#xf…

Kafka Kraft模式集群 + ssl

文章目录 启用集群资源规划准备证书创建相关文件夹配置文件启动各Kafka节点 故障转移测试spring boot集成 启用集群 配置集群时关键就是提前梳理好需要的网络资源,完成对应server.properties文件的配置。在执行前先把这些梳理好,可以方便后面的配置&…

[crxjs]自己创建一个浏览器插件

参考官方 https://crxjs.dev/vite-plugin/getting-started/vue/create-project 按照流程操作会失败的原因 是因为跨域的问题, 在此处添加 server: {host: "localhost",port: 5173,cors: true,headers: {"Access-Control-Allow-Origin": "*",}…

类的设计模式——单例、工厂以及建造者模式

1.单例模式 1.1 饿汉模式 单例模式:一个类只能创建一个对象,这个设计模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。 饿汉模式指在程序初始化时就创建一个唯一的实例对象。适用…

STM32之看门狗(IWDG)

一、看门狗外设的原理与应用 背景说明 随着单片机的发展,单片机在家用电器、工业自动化、生产过程控制、智能仪器仪表等领域的应用越来越广泛。然而处于同一电力系统中的各种电气设备通过电或磁的联系彼此紧密相连,相互影响,由于运行方式的…

跟着华为去变革 ——读《常变与长青》有感

《常变与长青》,是华为郭平总2024年上市的著作。走进这本书,我们能够清晰看到华为30多年的成长过程和伴随期间的变革历程:从一家设备代理商开始,起步蹒跚,砥砺前行,在闯过一个又一个磨难之后,成…

图像分割技术的实现与比较分析

引言 图像分割是计算机视觉领域中的一项基础技术,其目标是将数字图像划分为多个图像子区域(像素的集合),以简化图像表示,便于后续分析和理解。在医学影像、遥感图像分析、自动驾驶、工业检测等众多领域,图…

node.js配置变量

一、下载安装包 1、官网下载 大家可以在官网下载,适合自己电脑以及项目的需要的版本。 二、node.js安装 1、安装 双击下载的安装包文件,通常为 .exe 或 .msi 格式(Windows)或 .dmg 格式(Mac)。系统会…

Ubuntu+Docker+内网穿透:保姆级教程实现安卓开发环境远程部署

文章目录 前言1. 虚拟化环境检查2. Android 模拟器部署3. Ubuntu安装Cpolar4. 配置公网地址5. 远程访问小结 6. 固定Cpolar公网地址7. 固定地址访问 前言 本文将详细介绍一种创新性的云开发架构:基于Ubuntu系统构建Android仿真容器环境,并集成安全隧道技…

计算机网络总结(物理层,链路层)

目录 第一章 概述 1.基本概念 2.- C/S模式,B/S模式,P2P模式 3.- LAN,WAN,MAN,PAN的划分 4.电路交换与分组交换,数据报交换和虚电路交换 第二章 物理层 1.信号编码:不归零编码,曼切斯特编码 2.几种复用技术的特…

TIGER - 一个轻量高效的语音分离模型,支持人声伴奏分离、音频说话人分离等 支持50系显卡 本地一键整合包下载

TIGER 是一种轻量级语音分离模型,通过频段分割、多尺度及全频帧建模有效提取关键声学特征。该项目由来自清华大学主导研发,通过频率带分割、多尺度以及全频率帧建模的方式,有效地提取关键声学特征,从而实现高效的语音分离。 TIGER…

无人机降落伞设计要点难点及原理!

一、设计要点 1. 伞体结构与折叠方式 伞体需采用轻量化且高强度的材料(如抗撕裂尼龙或芳纶纤维),并通过多重折叠设计(如三重折叠缝合)减少展开时的阻力,同时增强局部承力区域的强度。 伞衣的几何参数&am…