当前位置: 首页 > news >正文

java并发编程 守护线程 用户线程 main

经常使用线程,没有对守护线程和用户线程的区别做彻底了解

下面写4个例子来验证一下

源码如下

/* Whether or not the thread is a daemon thread. */
private boolean     daemon = false;/*** Marks this thread as either a {@linkplain #isDaemon daemon} thread* or a user thread. The Java Virtual Machine exits when the only* threads running are all daemon threads.** <p> This method must be invoked before the thread is started.** @param  on*         if {@code true}, marks this thread as a daemon thread** @throws  IllegalThreadStateException*          if this thread is {@linkplain #isAlive alive}** @throws  SecurityException*          if {@link #checkAccess} determines that the current*          thread cannot modify this thread*/
public final void setDaemon(boolean on) {checkAccess();if (isAlive()) {throw new IllegalThreadStateException();}daemon = on;
}

看注释的含义是,daemon 为 true 时是守护线程,false 为用户线程。当所有守护线程在执行时 jvm 会退出。

守护线程无循环逻辑

public class DaemonThreadTest {public static void main(String[] args) {Thread thread = new Thread(() -> {System.out.println("这是一个守护线程");});// 设置守护线程thread.setDaemon(true);thread.start();}
}

执行结果无内容,说明 main 在执行完后就结束了,子线程没来得及执行。

守护线程有循环逻辑

public class DaemonThreadCycleTest {public static void main(String[] args) {Thread thread = new Thread(() -> {while (true) {}});// 设置守护线程thread.setDaemon(true);thread.start();System.out.println("主线程测试守护线程结束");}
}

执行结果

主线程测试守护线程结束

同上

用户线程无循环逻辑

public class UserThreadTest {public static void main(String[] args) {Thread thread = new Thread(() -> {System.out.println("这是一个用户线程");});thread.start();}
}

执行结果

这是一个用户线程

主线程结束后,子线程执行了。

用户线程有循环逻辑

public class UserThreadCycleTest {public static void main(String[] args) {Thread thread = new Thread(() -> {while (true) {}});thread.start();System.out.println("主线程测试用户线程结束");}
}

执行结果

主线程测试用户线程结束

此时,idea 显示程序执行还未结束,查看 jps 信息如下

C:\Users\Rike>jps
27776
852 Jps
34568
29100 UserThreadCycleTest
29468 RemoteMavenServer
30684 Launcher

说明主线程结束了,但是用户线程还在执行。

结论

守护线程的一个实现,jvm的垃圾回收,需要时创建,不需要时销毁。

如果希望 main 线程在结束后子线程马上结束,在创建时显式设置为守护线程。

如果希望 main 线程在结束后子线程继续执行,在创建时设置为用户线程或者不指定(默认为用户线程)。

决定程序是否还执行的是用户线程,但是用户线程一直持续会有资源消耗的问题。因为jvm每个线程与cpu一一对应,线程存在会一直占用操作系统和机器资源。

考虑到执行任务的问题,例如读取或者写入文件的时候,使用用户线程为好,但是需要设置退出策略。

疑问

https://www.jianshu.com/p/91028dca187b

个人猜测,main 线程是用户线程,如果是守护线程不符合逻辑,因为很多线程建立在它基础上,需要做很多关闭操作。看到这篇文章也是这样讲,但是没讲证据。正确性需要后面进行验证。

考虑到了线程池 ThreadPoolExecutor,看一下创建的线程是什么线程

ThreadPoolExecutor

public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), defaultHandler);}

如果 ThreadPoolExecutor 创建时 ThreadFactory 不指定,默认是 Executors.defaultThreadFactory(),可以自己指定。

ThreadFactory  建议是自己指定,在实际项目执行时如果有多个线程池未进行指定会无法区别是哪个线程池在执行,出现问题也不好排查,指定了线程池名称,通过日志可以快速定位到问题。

Executors

static class DefaultThreadFactory implements ThreadFactory {private static final AtomicInteger poolNumber = new AtomicInteger(1);private final ThreadGroup group;private final AtomicInteger threadNumber = new AtomicInteger(1);private final String namePrefix;DefaultThreadFactory() {SecurityManager s = System.getSecurityManager();group = (s != null) ? s.getThreadGroup() :Thread.currentThread().getThreadGroup();namePrefix = "pool-" +poolNumber.getAndIncrement() +"-thread-";}public Thread newThread(Runnable r) {Thread t = new Thread(group, r,namePrefix + threadNumber.getAndIncrement(),0);if (t.isDaemon())t.setDaemon(false);if (t.getPriority() != Thread.NORM_PRIORITY)t.setPriority(Thread.NORM_PRIORITY);return t;}}

Thread

public Thread(ThreadGroup group, Runnable target, String name,long stackSize) {init(group, target, name, stackSize);}

最终执行到 init(),发现通过当前线程运行是否是守护线程来决定是否创建守护线程。

可以看到,currentThread()默认取的是当前线程,然而当前线程一般是 main 线程,这就说明了线程池创建的线程默认是用户线程,想到这里符合后台任务处理的情况,防止主程序退出了后台任务也结束了。

参考链接

https://mp.weixin.qq.com/s/j_dwm-foKDTghMxwmdsz2w

https://blog.csdn.net/MaYuKang/article/details/121931517 

https://blog.csdn.net/weixin_34268604/article/details/114863702

相关文章:

java并发编程 守护线程 用户线程 main

经常使用线程&#xff0c;没有对守护线程和用户线程的区别做彻底了解 下面写4个例子来验证一下 源码如下 /* Whether or not the thread is a daemon thread. */ private boolean daemon false;/*** Marks this thread as either a {linkplain #isDaemon daemon} thread*…...

wxWidgets(1):在Ubuntu 环境中搭建wxWidgets 库环境,安装库和CodeBlocks的IDE,可以运行demo界面了,继续学习中

1&#xff0c;选择使用 wxWidgets 框架 选择这个主要是因为完全的开源&#xff0c;不想折腾 Qt的库&#xff0c;而且打包的文件比较大。 网络上面有很多的对比&#xff0c;而且使用QT的人比较多。 但是我觉得wxwidgets 更加偏向 c 语法本身&#xff0c;也有助学习C。 没有太多…...

[VIM]VIM初步学习-3

3-1 编写 vim 配置&#xff0c;我的 vim 我做主_哔哩哔哩_bilibili...

RocketMQ Dashboard说解

RocketMQ Dashboard 是 RocketMQ 的管控利器&#xff0c;为用户提供客户端和应用程序的各种事件、性能的统计信息&#xff0c;支持以可视化工具代替 Topic 配置、Broker 管理等命令行操作。 介绍​ 功能概览​ 面板功能运维修改nameserver 地址; 选用 VIPChannel驾驶舱查看 …...

【RabbitMQ实战】05 RabbitMQ后台管理

一、多租户与权限 1.1 vhost的概念 每一个 RabbitMQ服务器都能创建虚拟的消息服务器&#xff0c;我们称之为虚拟主机(virtual host),简称为 vhost。每一个 vhost本质上是一个独立的小型RabbitMQ服务器&#xff0c;拥有自己独立的队列、交换器及绑定关系等&#xff0c;并且它拥…...

PHP8中final关键字的应用-PHP8知识详解

在PHP8中&#xff0c;final的中文含义是最终的、最后的意思。被final修饰过的类和方法就是“最终的版本”。 如果关键字final放在类的前面&#xff0c;则表示该类不能被继承。 如果关键字final放在方法的前面&#xff0c;则表示该 方法不能被重新定义。 如果有一个类的格式为…...

基于Java的校园失物招领平台设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…...

〔024〕Stable Diffusion 之 模型训练 篇

✨ 目录 🎈 训练集准备🎈 训练集预处理🎈 数据清洗🎈 下载训练源码🎈 训练文件配置🎈 脚本运行🎈 实战测试🎈 训练集准备 声明: 该文中所涉及到的女神图片均来自于网络,仅用作技术教程演示,图片已码一般同一个训练集需要准备 20~40 张不同角度的照片,当然可…...

【MySQL入门到精通-黑马程序员】MySQL基础篇-DML

文章目录 前言一、DML-介绍二、DML-添加数据三、DML-修改数据四、DML-删除数据总结 前言 本专栏文章为观看黑马程序员《MySQL入门到精通》所做笔记&#xff0c;课程地址在这。如有侵权&#xff0c;立即删除。 一、DML-介绍 DML&#xff08;Data Manipulation Language&#xf…...

【ARMv8 SIMD和浮点指令编程】NEON 加载指令——如何将数据从内存搬到寄存器(LDxLDxR)?

将内存中的数据搬到 NEON 寄存器,有很多指令可以完成,熟悉这些指令是必须的。 1 LD1 (multiple structures) 将多个单元素结构加载到一个,两个,三个或四个寄存器上。该指令从内存中加载多个单元结构,并将结果写入一、二、三或四个 SIMD&FP 寄存器。 无偏移 一个寄存…...

华为云云耀云服务器L实例评测 | 实例场景体验之搭建个人博客:通过华为云云耀云服务器构建个人博客

华为云云耀云服务器L实例评测 &#xff5c; 实例场景体验之搭建个人博客&#xff1a;通过华为云云耀云服务器构建个人博客 介绍华为云云耀云服务器 华为云云耀云服务器 &#xff08;目前已经全新升级为 华为云云耀云服务器L实例&#xff09; 华为云云耀云服务器是什么华为云云耀…...

问题记录 springboot 事务方法中使用this调用其它方法

原因: 因为代理对象中调用了原始对象的toString()方法,所以两个不同的对象打印出的引用是相同的...

【Spring Cloud】Ribbon 实现负载均衡的原理,策略以及饥饿加载

文章目录 前言一、什么是 Ribbon二、Ribbon 实现负载均衡的原理2.1 负载均衡的流程2.2 Ribbon 实现负载均衡的源码剖析 三、Ribbon 负载均衡策略3.1 负载均衡策略3.2 演示 Ribbon 负载均衡策略的更改 四、Ribbon 的饥饿加载4.1查看 Ribbon 的懒加载4.2 Ribbon 的饥饿加载模式 前…...

Linux下基本指令(上)

文章内容&#xff1a; 1. ls 指令 语法&#xff1a; ls [选项][目录或文件] 功能&#xff1a;对于目录&#xff0c;该命令列出该目录下的所有子目录与文件。对于文件&#xff0c;将列出文件名以及其他信息。 单个ls显示当前目录下的文件和目录 常用选项&#…...

C++ 并发编程实战 第十一章 多线程应用的测试和除错

目录 11.1 与并发相关的错误类型 11.1.1 不必要的阻塞 11.1.2 条件竞争 11.2 定位并发错误的技术 11.2.1 代码审阅——发现潜在的错误 11.2.2 通过测试定位并发相关的错误 11.2.3 可测试性设计 11.2.4 多线程测试技术 11.2.5 构建多线程测试代码 11.2.6 测试多线程代…...

Redis实现API访问频率限制

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…...

BGP服务器租用价格表_腾讯云PK阿里云

BGP云服务器像阿里云和腾讯云均是BGP多线网络&#xff0c;速度更快延迟更低&#xff0c;阿里云BGP服务器2核2G3M带宽优惠价格108元一年起&#xff0c;腾讯云BGP服务器2核2G3M带宽95元一年起&#xff0c;阿腾云分享更多云服务器配置如2核4G、4核8G、8核16G等配置价格表如下&…...

时序分解 | Matlab实现SSA-VMD麻雀算法优化变分模态分解时间序列信号分解

时序分解 | Matlab实现SSA-VMD麻雀算法优化变分模态分解时间序列信号分解 目录 时序分解 | Matlab实现SSA-VMD麻雀算法优化变分模态分解时间序列信号分解效果一览基本介绍程序设计参考资料 效果一览 基本介绍 SSA-VMD麻雀搜索算法SSA优化VMD变分模态分解 可直接运行 分解效果好…...

【CSS如何实现双飞翼布局】

双飞翼布局是一种基于浮动布局的设计模式&#xff0c;主要用于实现三栏布局。它的主要特点是左右两列是浮动的&#xff0c;中间一列使用margin负值来达到“自适应”的效果。这种布局模式可以避免使用嵌套的div&#xff0c;同时也可以保证页面的语义结构清晰。以下是实现双飞翼布…...

服务注册发现机制

二、注册中心选型 1. zk和eureka的区别 zk&#xff1a;CP设计(强一致性)&#xff0c;目标是一个分布式的协调系统&#xff0c;用于进行资源的统一管理。 当主节点crash后&#xff0c;需要进行leader的选举&#xff0c;在这个期间内&#xff0c;zk服务是不可用的&#xff08;当然…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

SpringTask-03.入门案例

一.入门案例 启动类&#xff1a; package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

《C++ 模板》

目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板&#xff0c;就像一个模具&#xff0c;里面可以将不同类型的材料做成一个形状&#xff0c;其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式&#xff1a;templa…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...