【Java 基础篇】Java后台线程和守护线程详解

news2024/9/27 15:21:04

在这里插入图片描述

在Java多线程编程中,有两种特殊类型的线程:后台线程(Daemon Thread)和守护线程(Daemon Thread)。这两种线程在一些特定的场景下非常有用,但也需要谨慎使用。本文将详细介绍后台线程和守护线程的概念、特性、用法,以及注意事项。

什么是后台线程和守护线程?

后台线程(Daemon Thread)

后台线程是一种特殊类型的线程,它的生命周期取决于是否存在任何前台线程。当所有的前台线程都结束时,后台线程会自动退出。与前台线程不同,后台线程不会阻止JVM的退出。后台线程通常用于执行一些支持性工作,如垃圾回收、周期性任务等。

后台线程的创建方式是将线程对象的setDaemon(true)方法设置为true,表示将该线程设置为后台线程。

Thread backgroundThread = new Thread(() -> {
    // 后台线程的工作
});
backgroundThread.setDaemon(true);
backgroundThread.start();

守护线程(Daemon Thread)

守护线程是后台线程的一种特例。它具有后台线程的特性,但通常用于执行一些系统服务或周期性任务,而不是支持性工作。与后台线程一样,守护线程的生命周期也取决于前台线程的存在。

Java中的垃圾回收器就是一个典型的守护线程的例子。垃圾回收线程会在程序运行过程中自动回收不再使用的内存,无需程序员干预。

后台线程和守护线程的特性

了解了后台线程和守护线程的概念,接下来我们来看看它们的特性。

特性一:生命周期取决于前台线程

后台线程和守护线程的生命周期都取决于是否还有前台线程在运行。如果所有前台线程都结束了,那么后台线程和守护线程会自动退出。

特性二:不阻止JVM退出

后台线程和守护线程不会阻止JVM的退出。这意味着,如果所有前台线程都结束了,JVM会正常退出,而不管后台线程和守护线程是否还在运行。

特性三:适用于支持性任务

后台线程通常用于执行一些支持性任务,如日志记录、定时任务、连接池维护等。它们不会干扰程序的正常运行,但在必要时可以执行一些必要的工作。

特性四:不建议进行I/O操作

由于后台线程和守护线程的生命周期不受控制,因此不建议在这些线程中执行涉及I/O操作的任务。因为在I/O操作中,线程可能需要等待外部资源,而这可能导致线程在不合适的时候退出,从而引发不可预料的问题。

使用后台线程和守护线程的场景

下面我们来看看使用后台线程和守护线程的一些常见场景。

场景一:定时任务

后台线程和守护线程非常适合执行定时任务。你可以创建一个后台线程或守护线程来执行周期性的任务,例如定时清理临时文件、定时发送心跳包等。

Thread timerThread = new Thread(() -> {
    while (true) {
        // 执行定时任务
        try {
            Thread.sleep(1000); // 暂停1秒钟
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
});
timerThread.setDaemon(true); //

 设置为守护线程
timerThread.start();

场景二:垃圾回收

垃圾回收器是Java中的经典守护线程的例子。垃圾回收线程会自动回收不再使用的内存,无需程序员的干预。这是Java内存管理的重要组成部分。

public class GarbageCollectorExample {
    public static void main(String[] args) {
        // 创建一个后台线程来执行垃圾回收
        Thread garbageCollectorThread = new Thread(() -> {
            while (true) {
                System.gc(); // 手动触发垃圾回收
                try {
                    Thread.sleep(60000); // 每分钟执行一次垃圾回收
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        garbageCollectorThread.setDaemon(true); // 设置为守护线程
        garbageCollectorThread.start();

        // 模拟应用程序的主要工作
        for (int i = 0; i < 10; i++) {
            System.out.println("Main Thread is running...");
            try {
                Thread.sleep(2000); // 主线程每2秒输出一次
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在上面的示例中,我们创建了一个后台线程 garbageCollectorThread,它会每分钟执行一次垃圾回收。主线程会模拟应用程序的主要工作。由于 garbageCollectorThread 是后台线程,当主线程结束时,它会自动退出。

场景三:日志记录

在某些情况下,你可能希望在后台记录日志,而不干扰主要的应用程序流程。后台线程可以用于将日志信息写入文件或发送到远程日志服务器。

public class LoggingExample {
    public static void main(String[] args) {
        // 创建一个后台线程来执行日志记录
        Thread loggingThread = new Thread(() -> {
            while (true) {
                logMessage("This is a log message.");
                try {
                    Thread.sleep(5000); // 每5秒记录一条日志
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        loggingThread.setDaemon(true); // 设置为守护线程
        loggingThread.start();

        // 模拟应用程序的主要工作
        for (int i = 0; i < 10; i++) {
            System.out.println("Main Thread is running...");
            try {
                Thread.sleep(2000); // 主线程每2秒输出一次
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private static void logMessage(String message) {
        // 此处可以将日志信息写入文件或发送到远程日志服务器
        System.out.println("Logging: " + message);
    }
}

在上面的示例中,我们创建了一个后台线程 loggingThread,它会每5秒记录一条日志。主线程模拟应用程序的主要工作。 logMessage 方法用于记录日志信息,你可以根据实际需求将日志信息写入文件或发送到远程日志服务器。由于 loggingThread 是后台线程,当主线程结束时,它会自动退出。

这些示例演示了如何使用后台线程执行垃圾回收和日志记录任务,同时确保这些线程不会阻止应用程序的正常退出。

使用注意事项

在使用后台线程和守护线程时,需要注意以下几点:

注意一:生命周期不可控

后台线程和守护线程的生命周期不受程序控制,所以在设计任务时要确保任务可以随时被中断或重启。

注意二:不要进行I/O操作

由于线程的随时退出特性,不建议在后台线程和守护线程中进行I/O操作,以避免不可预料的问题。

注意三:不要执行长时间任务

后台线程和守护线程通常用于执行一些短时间的任务,不适合执行长时间的计算或等待操作。如果需要执行长时间任务,应考虑使用普通线程。

总结

后台线程和守护线程是Java多线程编程中的两个特殊类型的线程,它们的生命周期取决于是否存在前台线程,不会阻止JVM的退出。这两种线程通常用于执行支持性任务、定时任务、垃圾回收等工作。然而,在使用它们时需要注意生命周期不可控、不要进行I/O操作以及不要执行长时间任务等问题。合理使用后台线程和守护线程可以提高程序的性能和可维护性,但需要根据具体需求谨慎选择。希望本文能够帮助读者更好地理解和使用后台线程和守护线程。

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

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

相关文章

交换机端口汇聚详解

交换机端口汇聚是一种网络设计技术&#xff0c;用于将多个物理端口汇集成一个逻辑链路&#xff0c;以提供更高的带宽和冗余。通过端口汇聚&#xff0c;可以增加网络的吞吐量&#xff0c;并提高链路的可靠性和可用性。以下是关于交换机端口汇聚的详细介绍&#xff1a; 工作原理&…

【测试开发】用例篇 · 熟悉黑盒测试用例设计方法(1)等价类划分法、边界值法、判定表法

【测试开发】用例篇&#xff08;1&#xff09; 文章目录 【测试开发】用例篇&#xff08;1&#xff09;1. 测试用例的基本要素2. 测试用例的设计方法2.1 基于需求的设计方法&#xff08;设计测试点&#xff09;2.2 等价类划分法&#xff08;测试点>测试用例&#xff09;2.2.…

解锁 zkSync Era:开创全新的 Layer 2 扩展时代

作者: stellafootprint.network 数据来源: zkSync Dashboard 在解决以太坊扩展性问题方面&#xff0c;Layer 2 解决方案备受关注。这些解决方案旨在通过引入 Rollups, State Channels 或 Nested Blockchains 等技术来克服 Layer 1 的局限性。在 Layer 2 扩展领域&#xff0c;…

ROS Melodic安装

参考链接 链接: HinGwenWoong大佬 链接: 天月3大佬 本文用两篇文章互为参考&#xff0c;解决了两位大佬的文章在安装时产生的问题。 添加国内源 sudo sh -c . /etc/lsb-release && echo "deb http://mirrors.tuna.tsinghua.edu.cn/ros/ubuntu/ lsb_release -cs…

UWB定位模块

UWB定位模组是华星智控自研的小尺寸高集成度模组&#xff0c;模组长宽厚为30.1513.955.62毫米&#xff0c;天线采用IPEX接口分体式设计&#xff0c;方便集成于您的产品中&#xff0c;产品采用本安设计&#xff0c;可以用于煤矿等井下场景&#xff0c;通信距离>100米&#xf…

子网掩码的作用

1.子网掩码的作用 子网掩码是用来给ip划分网络位和主机位的。 子网掩码是为了给ip确定谁是网络地址、谁是主机地址的。子网掩码的二进制位是1的对应的是网络地址&#xff0c;子网掩码的二进制位是0的对应的是主机地址。

[PowerQuery] PowerAutoMate 刷新PowerBI 数据

通过PowerBI Automate 进行PowerBI 数据刷新之前,需要有Power Automate 授权或者Power Automate 试用账户,可以通过如下的地址进行申请注册。 https://flow.microsoft.com/zh-cn/ 完成Power Automate 登录之后,选中计划的云端流后创建,图为创建计划的云端流的操作步骤。 …

小程序随机生成文字卡片文案海报,带分享保存

概述 文字随机生成、更换头像、生成卡片、保存卡片、分享卡片 详细 文字随机生成、更换头像、生成卡片、保存卡片、分享卡片 数据是在data.js中 随机文案获取&#xff1a; demo直接在微信开发者工具可以运行 index.xml 代码 <view class"index"> <view …

02-HTML常用标签

02-HTML常用标签 2.1 标签的构成 标签由<、>、/、英文单词或字母组成。并且把标签中<>包括起来的英文单词或字母称为标签名常见标签由两部分组成&#xff0c;我们称之为&#xff1a;双标签。前部分叫开始标签&#xff0c;后部分叫结束标签&#xff0c;两部分之间…

C++ - AVL 树 介绍 和 实现 (上篇)

前言 之前我介绍了 二叉搜索树&#xff0c;可看一下博客&#xff1a;C - 搜索二叉树_chihiro1122的博客-CSDN博客 二叉搜索树的效率可以达到 O(log n) 。这个复杂度的算法的效率是非常恐怖的&#xff0c;2 的 30 次方大概是 10亿左右。也就是说 如果用暴力查找 需要找 10 亿次&…

HTTPS加密过程详解

目录 一、HTTPS是什么 1.1 运营商劫持 1.2 加密是什么 二、HTTPS的工作过程 2.1 对称加密 2.2 非对称加密 2.3 引入证书 一、HTTPS是什么 HTTPS 也是一个应用层协议。是在 HTTP 协议的基础上引入了一个加密层。 HTTP 协议内容都是按照文本的方式明文传输的。这就导致在传输过程…

Linux——vi编辑器

目录 一、基本简介 二、命令模式下的常用按键 1、光标跳转按键 2、复制、粘贴、删除 三、编辑模式 四、末行模式 1、查找关键字并替换 2、保存退出 3、其他操作 五、模式切换 一、基本简介 1、最早可追随到1991年&#xff0c;全称为“Vi IMproved” 2、模式 ——命…

【使用Cpolar将Tomcat网页传输到公共互联网上】

文章目录 1.前言2.本地Tomcat网页搭建2.1 Tomcat安装2.2 配置环境变量2.3 环境配置2.4 Tomcat运行测试2.5 Cpolar安装和注册 3.本地网页发布3.1.Cpolar云端设置3.2 Cpolar本地设置 4.公网访问测试5.结语 1.前言 Tomcat作为一个轻量级的服务器&#xff0c;不仅名字很有趣&#…

护网行动,最全攻略来啦!!!

随着网络技术的不断发展&#xff0c;网络领域被发现的安全威胁越来越多。 病毒入侵、数据窃取、网络攻击等安全事件时常发生&#xff0c;网络已然成为各国无声较量的重要战略空间。 为应对网络安全威胁&#xff0c;严守网络安全底线&#xff0c;公安部自2016年开始组织多家机构…

基于微信小程序的高校宿舍信息管理系统设计与实现(源码+lw+部署文档+讲解等)

前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f447;&#x1f3fb;…

Centos/Ubuntu安装redis

一、Centos安装redis 首先查看gcc是否安装 gcc -v 出现版本号就说明可以直接安装redis&#xff0c;没有的话需要安装gcc这是 下载路径&#xff1a; 【免费】gccCentos.rar资源-CSDN文库 rpm -ivh *.rpm --nodeps --force #安装 服务器有网的话可以直接下载redis包 wget https…

SpringBoot的学习要点

黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;_哔哩哔哩_bilibili博客阅读:Microservices中文文档&#xff1a;Spring Boot 中文文档 spring官网&#xff1a;https://start.spring.io/thymeleaf官方文档…

监控的分类

监控可以分成 4 个类别&#xff0c;具体如下&#xff1a; 业务监控 业务监控指标是管理层所关注的&#xff0c;一般与企业营收挂钩&#xff0c;或者跟客户主流程相关。这类指标类似 BI&#xff08;Business Intelligence System&#xff0c;即数据分析系统&#xff09; 数据…

【Html】用CSS定义咖啡 - 咖啡配料展示

显示效果 代码 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>CodePen - For The Love Of Coffee</title><link rel"stylesheet" href"./style.css">&l…

使用ZoeDepth生成深度估计图

目前单目深度估计分为两个派系&#xff0c;metric depth estimation(度量深度估计&#xff0c;也称绝对深度估计)和relative depth estimation(相对深度估计)。 ZoeDepth是 第一个结合相对和绝对深度的多模态单目深度估计网络。本博文仅记录使用ZoeDepth生成深度估计图的过程&a…