Java零基础之多线程篇:线程生命周期

news2024/11/24 0:38:28

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

  在并发编程中,多线程是一种非常重要的技术手段,理论知识及线程创建我已经在上一章节讲过了,本章我们就不再赘述。我们都知道Java作为一种广泛应用的开发语言,提供了丰富的多线程编程支持。了解并掌握Java多线程的生命周期对于编写高效且可靠的多线程程序至关重要。所以在本文中,我将介绍Java多线程的生命周期,包括线程状态的转换和对应的方法调用,作为新一期的内容进行讲解,这也是为了帮助大家学习上能够循序渐进。

摘要

  本文我的讲解思路是:首先通过简介介绍Java多线程的基本概念和特性,然后深入探讨线程的生命周期,包括线程的状态转换和相关的方法调用。此外,本文还将通过源代码解析、应用场景案例和优缺点分析等方式,帮助读者更好地理解和应用线程的生命周期。

简介

  多线程是指在一个程序中同时进行多个线程的执行,每个线程具有独立的执行路径。在Java中,每个线程都有自己的生命周期,包括新建、就绪、运行、阻塞和终止等不同状态。线程状态的转换由Java虚拟机自动控制,但是开发人员可以通过方法调用来干预线程的状态。

源代码解析

  在Java中,创建一个线程最常见的方式是继承Thread类或实现Runnable接口。以下是一个简单的示例代码:这里我们主要是以回顾+温习为主,毕竟上一章节已经学完的内容。

/**
 * @Author ms
 * @Date 2024-04-12 18:27
 */
public class MyRunnable implements Runnable {
    public void run() {
        // 线程执行的代码
        System.out.println("线程执行啦!");
    }
}


public class ThreadDemo {

    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();

        System.out.println("主线程执行啦!");
    }
}

  在上述代码中,MyThread类继承了Thread类,并重写了run方法。在ThreadDemo 类中,创建了一个MyThread实例,并调用start方法启动线程。

执行结果肯定如下所示:

在这里插入图片描述

  还不够熟练地同学,这里也可以再多敲敲试一下。

应用场景案例

  这里我们来谈谈,多线程可以应用于的各种场景,包括并发访问共享资源、提高程序性能、实现异步任务等。以下是几个常见的应用场景案例:

  1. 并发访问共享资源:多个线程同时访问同一个共享资源时,会出现竞态条件。使用多线程可以解决并发访问共享资源的问题,提高程序的执行效率。
  2. 提高程序性能:将耗时的任务拆分成多个子任务,用多线程同时执行,可以显著提高程序的运行速度。
  3. 实现异步任务:多线程可以在后台执行耗时的操作,让程序能够同时响应用户的输入和其他事件。

优缺点分析

  多线程编程有很多优点,同时也存在一些缺点,毕竟任何事物都要辩证看待。以下是对多线程编程的优缺点分析:

优点:

  • 提高程序的执行效率,充分利用多核处理器的计算能力。
  • 改善用户体验,使程序能够同时响应用户的输入和其他事件。
  • 实现复杂的并发控制,提高程序的可扩展性和可维护性。

缺点:

  • 多线程编程更加复杂,需要考虑线程安全、竞态条件等问题。
  • 线程间的通信和同步开销较大,可能引入死锁和性能损失等问题。
  • 调试和问题排查更加困难,因为多线程程序的执行顺序不确定。

类代码方法介绍

在Java中,线程类常用的方法有以下几种:

  • start():启动线程,并调用线程的run方法。
  • sleep():使线程进入休眠状态,暂停执行一段时间。
  • join():等待线程执行完毕,再继续执行当前线程。
  • interrupt():中断线程的执行。

熟悉上述方法后,我们就要来实战演示了。

Java代码测试用例

以下是一个简单的Java多线程测试用例,用于计算从1到10的累加和,代码演示如下,仅供参考:

package com.example.javase.ms.threadDemo.day2;

/**
 * @Author ms
 * @Date 2024-04-12 19:09
 */
public class MyThread extends Thread {
    
    private static int sum = 0;

    public void run() {
        for (int i = 1; i <= 10; i++) {
            sum += i;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MyThread thread1 = new MyThread();
        MyThread thread2 = new MyThread();
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println("Sum is: " + sum);
    }
}

  在上述代码中,MyThread类继承了Thread类,并重写了run方法。在主线程中,创建了两个MyThread实例,并分别启动两个线程。最后,使用join方法等待两个线程执行完毕,并打印累加和。

测试结果展示:

  当程序运行时,它将创建两个线程,每个线程都会独立地计算从1到10的和。由于线程的执行是由操作系统的线程调度器控制的,所以两个线程完成计算的顺序是不确定的。但是,由于join()方法的使用,我们可以确保在主线程打印sum的值之前,两个线程都已经完成了它们的计算。结果展示如下:

在这里插入图片描述

  其实上述代码,从执行结果上来看,不知道大家有没有发现问题!可以评论区交流下,虽然我下文也会给出对应的代码优化。

测试代码解析:

  根据如上代码作出解析,以便于同学们更好的理解,分析如下:

  如上测试用例展示了一个简单的多线程示例,其中创建了两个线程,每个线程都执行一个for循环来计算从1到10的整数和。这个示例使用了Thread类来创建和管理线程。

  1. MyThread类继承了Thread类,并重写了run()方法。在run()方法中,通过一个循环计算从1到10的整数和,并将结果累加到静态变量sum中。

  2. main方法中,创建了两个MyThread对象:thread1thread2,并且分别启动了这两个线程。

  3. thread1.join();thread2.join();这两行代码使得主线程等待thread1thread2完成执行。join()方法确保了在主线程继续执行之前,当前线程(在这个例子中是thread1thread2)已经终止。

  4. 最后,一旦两个线程都完成了它们的计算,主线程将打印出静态变量sum的值。

注意事项

  • 由于sum是一个静态变量,它在所有MyThread实例之间共享。这意味着两个线程都会访问和修改同一个sum变量,这可能导致线程安全问题,如竞态条件。这里就是我上述所提到的问题。
  • 在这个特定的例子中,由于每次只有一个线程在执行run()方法,所以不会出现竞态条件。但是,如果sum的更新是在多个线程中并发进行的,那么就需要使用同步机制来确保线程安全。

改进建议

  那么如何避免潜在的线程安全问题呢?其实很简单,这里我们可以使用synchronized关键字来同步对sum的访问。优化代码如下:

/**
 * @Author ms
 * @Date 2024-04-12 19:14
 */
public class MyThread_update extends Thread {
    private static final Object lock = new Object();
    private static int sum = 0;

    public void run() {
        for (int i = 1; i <= 10; i++) {
            synchronized (lock) {
                sum += i;
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MyThread_update thread1 = new MyThread_update();
        MyThread_update thread2 = new MyThread_update();
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println("Sum is: " + sum);
    }
}

  在这个改进的版本中,我们使用了一个对象lock作为同步锁。在每次更新sum变量时,我们都会获取这个锁,这样可以确保在同一时间只有一个线程能够执行更新操作。这有助于防止多个线程同时写入sum变量,从而避免竞态条件。

  然后,我们再来执行测试一下,结果展示如下:

在这里插入图片描述

全文小结

  本文介绍了Java多线程的生命周期,包括线程状态的转换和对应的方法调用。通过源代码解析、应用场景案例和优缺点分析等方式,帮助读者更好地理解和应用线程的生命周期。同时,通过Java代码测试用例演示了多线程的具体应用。

总结

  了解和掌握Java多线程的生命周期对于编写高效且可靠的多线程程序至关重要。本文通过介绍线程的状态转换、方法调用和具体应用场景,为读者提供了丰富的知识和实践经验。通过合理地应用多线程技术,开发人员可以提高程序的执行效率,改善用户体验,并解决复杂的并发控制问题。

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。

⭐️若有疑问,就请评论留言告诉我叭。

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

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

相关文章

数据库 | SQL语言和关系代数汇总篇(*^▽^*)

双重/两个 not exists 嵌套查询 简单分析_两个not exists-CSDN博客 最明白的 not exists 双层嵌套讲解 SQL 查询语句_not exist 嵌套-CSDN博客 1. 答案&#xff1a; 2. 答案&#xff1a; 3. 4. 5. 6. 7. 8. 这个SQL查询是从两个表&#xff08;假设是SPJ和P&#xff09;中检…

Ubuntu服务器搭建Git远程仓库

本文所述方法适用于小型团队在局域网环境中使用Git进行代码版本管理。 1. 安装Git 打开终端(Ctrl + Alt + T) ,输入以下命令: sudo apt update #更新软件包列表信息 sudo apt install git #安装Git 验证Git是否安装成功,可以查看Git版本: git --version 也需…

Java基础入门day63

day63 JSON Jackson方式 package com.saas.test; ​ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.saas.entity.Student; import com.saas.entity.Birth; ​ import java.io.IOException; i…

大学生技能科普 | office 办公软件技能掌握 暑期电脑办公软件培训

为什么要学office&#xff1f; 提高工作效率&#xff1a;通过学习和掌握Office办公软件&#xff0c;可以更加高效地完成文档编辑、数据处理、图表制作等任务。 增强个人竞争力&#xff1a;在当今职场竞争中&#xff0c;熟练掌握Office办公软件已经成为一项基本的技能要求。掌…

FreeRTOS源码分析

目录 1、FreeRTOS目录结构 2、核心文件 3、移植时涉及的文件 4、头文件相关 4.1 头文件目录 4.2 头文件 5、内存管理 6、入口函数 7、数据类型和编程规范 7.1 数据类型 7.2 变量名 7.3 函数名 7.4 宏的名 1、FreeRTOS目录结构 使用 STM32CubeMX 创建的 FreeRTOS 工…

《STM32 HAL库》小米微电机控制例程——通信协议分析及驱动库

之前有段时间因为机器狗项目的缘故&#xff0c;一直在使用小米微电机&#xff0c;但是苦于没有一个详尽的奶妈级教程&#xff0c;在控制电机的学习中踩了不少的坑。今天咱们就从头至尾一步一步的实现使用按键控制小米微电机。本文将会分析小米电机驱动库&#xff0c;并简要介绍…

Web3新视野:Lumoz节点的潜力与收益解读

摘要&#xff1a;低估值、高回报、无条件退款80%...... Lumoz正通过其 zkVerifier 节点销售活动&#xff0c;引领一场ZK计算革命。 长期以来&#xff0c;加密市场以其独特的波动性和增长潜力&#xff0c;持续吸引着全球投资者的目光。而历史数据表明&#xff0c;市场往往在一年…

RAG 流程及论文串烧

文档切片 文档切片的五个层次 https://medium.com/anuragmishra_27746/five-levels-of-chunking-strategies-in-rag-notes-from-gregs-video-7b735895694d#b123 Basic RAG 与 Advanced RAG https://pub.towardsai.net/advanced-rag-techniques-an-illustrated-overview-04d…

pytorch库 02 Anaconda、Jupyter常用命令及操作

文章目录 一、Anaconda Prompt1、conda常用命令2、pip常用命令 二、Jupyter1、Jupyter常用命令及基本操作2、Jupyter代码补全插件安装 一、Anaconda Prompt 1、conda常用命令 下列命令可以在Anaconda Prompt中输入。 清屏&#xff1a; cls 查看帮助&#xff1a; conda -h 查…

Hadoop升级失败,File system image contains an old layout version -64

原始版本 Hadoop 3.1.3 升级版本 Hadoop 3.3.3 报错内容如下 datasophon 部署Hadoop版本 查看Hadoop格式化版本 which hadoop-daemon.sh/bigdata/app/hadoop-3.1.3/sbin/hadoop-daemon.sh删除原来的旧版本 rm -rf /bigdata/app/hadoop-3.1.3查看环境变量 env|grep HADOOPHAD…

SSRF(2)

Gopher协议的利用 gopher协议是ssrf利用中最强大的协议 gopher协议支持发出GET、POST请求&#xff1a; 可以先截获get请求包和post请求包&#xff0c;再构成符合gopher协议的请求。 默认端口为70,一般需发送到80端口 如果发起post请求&#xff0c;回车换行需要使用%0D%0A&…

Java面试八股之myBatis与myBatis plus的对比

myBatis与myBatis plus的对比 基础与增强&#xff1a; MyBatis 是一个成熟的Java持久层框架&#xff0c;它允许开发者通过XML文件或注解来配置SQL语句和数据库映射&#xff0c;提供了一个灵活的方式来操作数据库&#xff0c;但需要手动编写所有的SQL语句和结果集映射。 MyBa…

AI系统进入临床实践的几点考量——DECIDE-AI读后感

AI系统进入临床实践的几点考量——DECIDE-AI读后感 DECIDE-AI是一个新的阶段性报告指南&#xff0c;用于早期的临床评估基于人工智能&#xff08;AI&#xff09;的决策支持系统。它由欧洲影像学和医学人工智能实验室&#xff08;IDEAL&#xff09;合作开发&#xff0c;旨在解决…

60.指针数组和数组指针

一.指针数组 指针数组是一个数组&#xff0c;在指针数组中存放的是指针变量。 定义一个指针数组p int *p[5]; 内存模型如下&#xff1a; 指针数组的初始化 #include <stdio.h>int main(void) {int a1;int b2;int c3;int i;int *p[3] {&a,&b,&c};for(i0…

hdfs源码解析之DFSClient

1、DFSClient类简介 DFSClient 是 Hadoop 分布式文件系统&#xff08;HDFS&#xff09;中的一个核心类&#xff0c;用于客户端与 HDFS 之间的交互。它提供了一组方法&#xff0c;使客户端应用程序可以方便地与 HDFS 进行通信&#xff0c;包括文件的读取、写入、创建、删除、重命…

Nidhogg:一款专为红队设计的多功能Rootkit

关于Nidhogg Nidhogg是一款专为红队设计的多功能Rootkit&#xff0c;该工具的主要目的是为红队研究人员提供一个多合一的切易于使用的多功能Rootkit&#xff0c;并允许研究人员通过单个头文件来将其引入到自己的C2框架之中。 当前版本的Nidhogg支持任意版本的x64 Windows 10和…

git的Cherry pick

Cherry pick Git Cherry Pick详解 https://blog.csdn.net/jam_yin/article/details/131594716 目标: 将开发分支A中提交的部分内容合并到B分支(可能是测试分支) 步骤: vscode安装 点击下图标进入graph

【golang学习之旅】使用VScode安装配置Go开发环境

1. 下载并安装Go1.1 下载地址1.2 选择版本并下载1.3 安装目录1.4 验证是否安装成功 2. 配置环境变量2.1 配置步骤2.2 GO部分环境变量说明 3. 下载或更新 Vscode3.1 下载地址3.2 安装步骤 4. 为Go开发配置VScode 1. 下载并安装Go 1.1 下载地址 https://studygolang.com/dl 1.…

压缩pdf文件大小,如何压缩pdf

压缩PDF文件是现代办公中常见的需求&#xff0c;因为PDF文件往往包含了大量的图片、文本和格式信息&#xff0c;导致文件体积较大&#xff0c;不利于传输和存储。本文将详细介绍如何压缩PDF文件&#xff0c;我们一起来看一下。 浏览器打开 "轻云处理pdf官网" &#x…

计网重点面试题-TCP三次握手四次挥手

三次握手 第一次握手(syn1) 客户端会随机初始化序号&#xff08;client_isn&#xff09;&#xff0c;将此序号置于 TCP 首部的「序列号」字段中&#xff0c;同时把 SYN 标志位置为 1&#xff0c;表示 SYN 报文。接着把第一个 SYN 报文发送给服务端&#xff0c;表示向服务端发…