JAVA多线程基础篇 1、线程概念与线程生命周期

【JAVA】多线程基础:线程生命周期与状态切换(31) Java多线程是程序执行的最小单元,允许同时执行多个任务,提升效率和资源利用率。其生命周期包括新建、就绪、运行、阻塞、等待、超时等待和终止状态,状态间通过不同方法切换。多线程适用于提高性能(如并行处理数据)和异步操作(如文件下载、网络请求)。实际应用中,多线程可用于文件下载(将文件分块并行下载)和网络爬虫(多线程爬取网页)。通过合理使用多线程,可以显著提升程序的执行效率和用户体验。 阅读详情

1. 掌握多线程编程的重要性

  • 理解了多线程,才能理解了现代分时操作系统,并进一步理解更多系统应用组件的底层原理。

  • 并发编程是低级程序员跨越到中高级程序员必过一关,是区分程序员水平的最常用的标准。在程序员求职过程中,多线程知识会被频繁问及考察,几乎所有的招聘要求里都会要求熟悉高并发编程。

2. 为何使用线程

在计算机早期并没有多线程的概念,程序在纸带上编码送入计算机运行,但是由于计算机当时是非常昂贵的,如何提高计算机CPU利用率这一问题提出了。
这一问题的提出,引发了一系列技术的进展,计算机处理任务的一步步演化。
单进程=>多进程批处理=>多进程并行处理=>多线程处理=>协程(纤程)
使用线程后,同一个程序可以创建多个任务,进一步压榨CPU能力。

3.进程、线程

  • 进程是操作系统进行资源分配的基本单位。
    当计算机运行可执行文件时,计算机开辟内存空间、分配文件描述符以及端口等一系列资源。进程是独立拥有这些资源的基本单位。注意,一个程序可以创建多个进程,比如我们同时可以在电脑上打开多个浏览器窗口或者登录多个QQ。所以说,进程是静态资源的概念。

  • 线程是操作系统进行资源调度的基本单位。
    所有的程序的运行都是以线程为单位来执行的。一个程序在运行的时候,至少包含一个线程,即主线程。如果一个程序运行过程中,有多个“执行路径”,即是多线程程序。线程运行过程中,由于CPU轮转等原因,会发生线程切换。所以说,线程是动态调度的概念。

    单CPU机器有必要用多线程吗?
    多线程能够合理利用CPU和IO资源,有利于提高程序性能。

    线程数是否越多越好?
    线程切换会消耗资源,因此不是越多越好。

    线程数设置多少合适?
    以CPU核数和实际压测结果定,估算线程数需要综合考虑CPU核数、CPU利用率、程序的响应时间。

4. 多线程编程的复杂性

在计算机体系的发展过程中,CPU、内存、IO速度有非常大的差别。
根据估算CPU速度是内存读取速度的1000倍以上。,内存是磁盘IO或网络IO的1000倍以上。

  • 为了解决CPU与内存速度适配的问题,增加了缓存的设计。
  • 为了优化使用缓存,编译程序会优化指令的执行次序。
  • 为了解决CPU与IO速度的差异,增加了线程的设计,以分时复用CPU

这就导致了并发编程需要注意的三个问题。

  • 可见性问题 (剧透,可使用volatile synchronized 解决)
  • 有序性问题 (剧透,可使用volatile synchronized 解决)
  • 原子性问题 (剧透,可synchronized 解决)

5. 线程的生命周期

线程状态

6. 线程的状态

  1. NEW : 线程刚刚创建,还没有启动。
  2. RUNNABLE :可运行状态,分为READY和RUNNING。均是可运行状态。当Thread.yield()时,线程主动礼让。
  3. WAITING:等待被唤醒。
  4. TIMED WAITING:隔一段时间后自动唤。
  5. BLOCKED:被阻塞,正在等待锁。
  6. TERMINATED:线程结束。

6.1 实验观察线程状态(一)

  • 观察NEW、RUNNABLE、TERMINATED状态
public class ThreadStateMonitor1 {
    public static void main(String[] args) throws InterruptedException {
        /*
        观察 NEW RUNNABLE TERMINATED 状态
        * */
        Thread t1 = new Thread(()->{
            for(int i=0;i<3;i++) {
                System.out.print(Thread.currentThread().getState());
                System.out.println("do something " + i);
            }
        });
        System.out.println(t1.getState());
        t1.start();
        //join 方法在此处表示,main线程等待t1完成线程方法。
        t1.join();
        System.out.println(t1.getState());
    }
}

运行结果:

线程状态1

6.2 实验观察线程状态(二)

  • t1线程start后,就立即拿到锁。
  • 接着,o.wait() 就会释放锁,并进入到WAITING状态。如果o.wait(1000),会进入TIMED WAITING状态。
  • MAIN方法的主线程接着拿到锁,并叫醒t1,t1醒后就开始排队争抢锁,进入BLOCKED状态。
  • 最后t1拿到了锁,记者开始执行wait()之后的命令,打印"我wait好了。我执行到这里的时候,表示又获得了锁"
  • 最后main等待t1一起“退休”,进入TERMINATED状态。
public class ThreadStateMonitor2 {
    public static void main(String[] args) throws InterruptedException {
        //o是一个锁对象
        Object o = new Object();
        //让t1线程获得o的锁后,就等待被唤醒
        Thread t1 = new Thread(()->{
            synchronized (o) {
                System.out.println("我获得了锁");
                try {
                    //o.wait(1000);
                    o.wait();
                    System.out.println("我wait好了。我执行到这里的时候,表示又获得了锁");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();
        //MAIN线程让t1先执行一会
        Thread.sleep(100);
        //这个时候t1已经wait了
        System.out.println(t1.getState());
        synchronized (o){
            o.notify();
            System.out.println(t1.getState());
        }
        Thread.sleep(100);
        //t1
        t1.join();
        System.out.println(t1.getState());
    }
}

运行结果:
线程状态2

7. 线程的常用方法

7.1 Thread类上的方法

作用在线程上,由线程对象执行。

  • Thread.start(),通过 Thread 调用 start() 方法来启动线程。在Thread内部以静态代理的方式运行Runnable对象的run的方法。
  • Thread.sleep(millisec),是Thread类的静态方法,会休眠当前正在执行的线程,millisec 单位为毫秒。sleep()不会释放当前拿到的锁。
  • Thread.join(),在线程A调用线程B的 join() 方法后,A会直到B线程结束才会执行后续指令。
  • Thread.yield(),线程礼让,建议线程调度器调度其他线程运行,最终礼让结果由操作系统实现。

7.2 Object类上的方法

作用在锁对象上。

  • Object.wait(),调用 wait() 使得线程进入等待被唤醒的队列,wait后会释放锁资源。等待被唤醒。
    这是因为,如果没有释放锁,那么其它线程就无法进入对象的同步方法或者同步控制块中,那么就无法执行 notify() 或者 notifyAll() 来唤醒挂起的线程,造成死锁。
  • Object.notify() 唤醒在Object上的等待队列的某一个线程,由操作系统决定。
  • Object.notifyAll() 唤醒在Object上的等待队列所有线程。

7.3 Condition类上的方法

java.util.concurrent 类库中提供了 Condition 类来实现线程之间的协调,可以在 Condition 上调用 await() 方法使线程等待,其它线程调用 signal() 或 signalAll() 方法唤醒等待的线程。相比于 wait() 这种等待方式,await() 可以指定等待的条件,因此更加灵活。

8 线程安全

线程安全指的是程序在多线程环境里的执行,是符合预期的。要实现线程安全首先需要考虑竞态条件。对于无状态的线程,是绝对安全的。对于共享状态的线程,需要考虑可见性、指令顺序性和原子性等多个情况。因为多线程的执行是复杂的、但是JAVA多线程的原理和技术并不是难以掌握的。记住,并不比掌握手动挡的档位复杂。

总结

线程是cpu调度的基本单位,线程的生命周期中会经过多种状态的变化,就像人生,有生有死、有争有夺、有等待、有迷惘。也有其忙碌、专注的时刻。

多线程系列在github上有一个开源项目,主要是本系列博客的实验代码。

https://github.com/forestnlp/concurrentlab

如果您对软件开发、机器学习、深度学习有兴趣请关注本博客,将持续推出Java、软件架构、深度学习相关专栏。

您的支持是对我最大的鼓励。

【Java篇】多线程详解 Java系统在语言层次上对多线程直接提供支持,多线程的主要目的是将一个程序中的各个程序段并发化,在在通常情况下,Java程序各部分是按顺序一次执行的,由于某种原因,需要将这些按顺序执行的程序段转化为并发执行,每个程序段在逻辑上是相互完整的代码段。实际上,在单处理器上,同一时刻只能执行一个代码,但是在同一时间段内,这些代码交替执行,所谓的“微观串行,宏观并行”。... 阅读详情

相关推荐

深入Java多线程:基础篇,你必须掌握!| 多线程篇(一)

🏆本文收录于「Java进阶实战」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

**My Coding Family** 1607

线程(线程基本概念、java实现多线程、使用多线程、线程的生命周期、线程同步、线程死锁)

线程(线程基本概念、java实现多线程、使用多线程、线程的生命周期、线程同步、线程死锁)

H215919719的博客 9562

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

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

喵手的博客 1255

多线程基础(一): 线程概念及生命周期

文章目录1.基本概念1.1 进程1.2 线程1.3 协程2 线程生命周期2.1 传统的线程模型2.2 java中的线程模型2.2.1 从NEW到RUNNABLE状态2.2.1.1 继承Thread类2.2.1.2 实现Runnable接口2.2.2 RUNNABLE与WAITING状态转换2.2.3 RUNNABLE与TIME_WAITING状态转换2.2.4 RUNNING与BLOCKED的转换2.2.5 从RUNNING到TERMINATED状态3.总结 终于完成了前面关于Map容器的源码阅读部分,并进

dhaibo1986的专栏 520

多线程基础:创建与启动线程,线程的生命周期!

Java多线程的引入使得我们能够充分利用现代多核CPU的性能,同时让程序能够同时执行多个任务。在多线程编程中,理解线程的生命周期、线程的创建和启动方式,以及如何正确管理线程的执行,是构建高效多线程程序的基础。Java中的多线程编程为我们提供了强大的并发执行能力,理解线程的生命周期、如何创建和启动线程、以及如何管理线程的状态对于构建高效、稳定的应用程序至关重要。通过继承Thread类或实现Runnable接口,我们可以轻松地创建和启动线程。

喵手的博客 737

摄像头visio_最全面弱电智能VISIO图标集(百个),高大上方案就靠这个了

原标题:最全面弱电智能VISIO图标集(百个),高大上方案就靠这个了不会用Visio,Visio画拓扑画的很丑,怎么办?本期sin66小编免费分享一份最全面的弱电智能VISIO图标集(百个)给大家,以后画拓扑、做方案,直接高大上起来!需要本期资料直接看文末!!接下来我们一起看一下这些Visio图标大全:我们从下图可以看出前端设备主要是由枪机,筒机,无线摄像头,半球,球机,USB摄像头等构成,对于绘...

weixin_39644915的博客 1万+

Java中的线程基础篇-线程基本概念

Java中的线程一、基础知识1. 进程、线程、协程1.1 进程1.2 线程1.3 协程2. 串行、并发、并行2.1 串行2.2 并发2.3 并行二、线程的创建1. 继承Thread类1.1 实现步骤1.2 特点2. 实现Runnable接口2.1 实现步骤2.2 与Thread相比3. 实现Callable接口(JDK5.0新增)3.1 实现步骤3.2 与Runnable接口相比三、线程的常用方法四、线程的生命周期1. 基本概念2. 六个状态 一、基础知识 1. 进程、线程、协程 1.1 进程 基本概念

weixin_44446626的博客 2342

MOSFET和IGBT栅极驱动器电路的基本原理学习(2)

1.PWM直接驱动 驱动主开关晶体管栅极的最简单方法是利用 PWM 控制器的栅极驱动输出,如图 (1)如 图 8中所示,PWM 控制器和 MOSFET 之间可能有较大距离。由于栅极驱动和接地环路迹线形成的环路,这个距离形成了寄生电感,从而降低了开关速度,并导致栅极驱动波形中形成振铃。为了降低与栅极驱动连接相关的电感,需要更宽的 PCB 迹线。 (2)直接栅极驱动的另一个问题是PWM 控制器的驱动电流能力有限。极少有集成电路能提供高于 1A 的峰值栅极驱动能力。 2.旁路电容的确定 (1)位置 如果是独立的

weixin_43732932的博客 5831

JAVA ——线程概念(线程的生命周期及使用)

线程的生命周期 首先让我们了解一下java中线程的周期 分为几种状态: 新建 NEW 运行 RUNNING 阻塞 BLOCKING 死亡 DEAD 线程常用方法 方法 介绍 start() 启动 stop() 停止(禁用,可能导致线程死锁等问题),停止线程可以让run执行结束 String getName() 获得线程的名字 setName(String) 设置线程名字 sleep(long) 进入睡眠,毫秒 setPriority(int) 设置线程的优先级(1~

m0_45147931的博客 371

temu登录接口逆向分析(含Py纯算)

【代码】temu登录接口逆向分析(含Py纯算)

数据精灵喵 1946

Python读取三菱PLC数据

3、支持自定义的数据读写操作。直接调用Read方法,可以读取到原生的byte数组,然后进行组合数据。1、每次的数据交互您都可以判断是否成功,如果您不判断,如果网络断开或是异常,会影响程序的执行。Qna3E协议的ascii类 MelsecMcAsciiNet。A兼容1E协议的二进制类 MelsecA1ENet。Qna3E协议的二进制类 MelsecMcNet。2、读写操作支持单个数和数组。

weixin_46744807的博客 1998

JAVA线程的生命周期(以及操作线程的方法详解)

线程具有生命周期,其中包含5种状态,分别为出生状态、就绪状态、运行状态、暂停状态(包括休眠、等待和阻塞等)和死亡状态。 出生状态:就是线程被创建时的状态;就绪状态:线程对象调用start()方法后,线程处于就绪状态(又称为可执行状态);运行状态:当线程得到系统资源后就进入了运行状态,一旦进入运行状态,他会在就绪与运行状态下转换,同时也有可能进入暂停或死亡状态;暂停(阻塞)状态:当线程调用sleep()方法、wait()方法或者发生阻塞时会进入暂停状态。当线程休眠结束、调用notify或notifyAll方法

怪咖@的博客 2014

基于最小二乘法(LS)和最小均方误差(MMSE)算法的导频信道估计

导频信道估计在无线通信系统中起着至关重要的作用,它用于估计无线信道的特性,以便在接收端进行正确的信号解调和解码。最小二乘法(LS)和最小均方误差(MMSE)是两种常用的导频信道估计算法,它们在估计精度和计算复杂度之间取得了良好的平衡。首先,我们提取当前的导频符号,然后将接收到的信号与导频符号相乘得到接收导频信号。最小二乘法是一种经典的导频信道估计算法,它通过最小化接收信号与预测信号之间的均方误差来估计信道。下面将详细介绍基于LS和MMSE算法的导频信道估计,并提供相应的MATLAB代码实现。

pytorchCode的博客 680

Java 多线程基础概念

什么是进程? 进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。操作系统在运行一个程序时,会为其创建一个进程。 什么是线程? 线程与进程类似,但线程是一个比进程更小的执行单元,一个进程在执行过程中可以产生多个线程,线程是操作系统调度的最小单元。 在 Java 中,同一进程的多个线程共享该进程的堆和方法区资源,但每个线程都有自己独立的程序计数器、虚拟机栈和本地方法栈,所以系统在线程之间切换工作的负担要比进程小,因此线程也被叫做轻量级进程。 Java

明月燃雨 1万+

图片风格自动分析模型

对于分类任务,我们可以使用交叉熵损失作为损失函数。同时,我们可以选择随机梯度下降(SGD)或Adam等优化器进行模型优化。# 使用SGD优化器# 或使用Adam优化器在这部分,总结整个项目的过程,包括数据准备、模型构建、训练、优化和评估等。同时,讨论可能的改进方向和未来工作,例如尝试更多的模型结构、优化技巧等。

a871923942的博客 1698

SAP_通用模块-MASS批量操作技巧

SAP_MM模块-MASS/MM17批量更新主数据详细教程

风沙的博客 2168

Java 多线程基础:彻底搞懂进程与线程的区别及线程生命周期

本文深入浅出地讲解了Java多线程的核心概念。首先通过生活场景类比,说明进程和线程的区别:进程是独立资源分配单位,线程是轻量执行单元,共享进程资源。文章从资源占有、开销、独立性三个维度对比分析,并形象比喻为;独立豪宅;和;共享公寓;。接着详细解析线程生命周期的5种状态(新建、就绪、运行、阻塞、终止)及其转换条件,配合代码示例验证状态转换。最后强调理解这些基础概念对排查线程问题的重要性,为后续学习线程同步、线程池等内容奠定基础。

qq_40303030的博客 1582

【零基础入门unity游戏开发——2D篇】大大简化了地形创建流程,减少Rule Tile的使用 —— AutoTile自动平铺瓦片的使用介绍

Unity 2D游戏开发中的AutoTile技术详解 摘要:本文详细介绍了Unity 2D游戏开发中的AutoTile技术,这是一种智能瓦片系统,能够自动处理地形和场景拼接。文章首先讲解了AutoTile的基本概念和优势,然后分步骤指导读者如何安装2D Tilemap Extras包、创建AutoTile、设置参数和绘制遮罩。通过实际案例演示了AutoTile的使用方法,并比较了AutoTile与Rule Tile的适用场景。最后指出AutoTile虽然使用方便,但对素材要求较高,开发者应根据项目需求选择合

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 729

Java基础-Java多线程机制

学习目标:了解java多线程机制

来自想要赚大钱的小周同学 2409

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

【java基础】多线程(超详细)

在本文中,介绍了java线程的基本知识,包括线程的创建与启动、线程的生命周期等内容

weixin_44571502的博客 1883

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Java多线程初阶-基础概念与线程操作

本篇笔记介绍了JavaEE中的重要一站,理解和掌握多线程是提升程序性能、构建高响应应用的关键。这篇文章可以作为多线程学习之旅的起点,旨在帮助初学者建立对线程的清晰认识。内容将从“什么是线程”这个基本问题出发,探讨其与进程的区别,并动手编写第一个多线程程序。接着,会深入学习`Thread`类的常用方法,掌握如何创建、启动、中断和等待一个线程。最后,会全面解析线程的生命周期与各种状态,为后续理解更复杂的并发问题打下坚实的基础。

weixin_73966418的博客 1357

【Java基础知识8】多线程与并发

介绍多线程之前要介绍线程,而介绍线程则离不开进程1.进程在计算机中,我们把一个任务称为一个进程,浏览器就是一个进程,视频播放器是另一个进程,类似的,音乐播放器和Word都是进程。

阿志的博客 1369

【Java】多线程、线程的创建、生命周期、多线程同步

本文主要讲解多线程、线程的创建、生命周期、多线程同步等相关问题~

Le vent se lève, il faut tenter de vivre 918

java学习之多线程篇学习总结

提到多线程,首先要学习一些概念性的词汇,线程和进程,并行和并发。一个正在系统上执行的程序为一个进程,一个进程包含多个线程。线程是操作系统能够进行运算调度的最小单位,多个线程会存在共享数据的情况。并行是实现多任务处理的方式。并行处理可以提高处理速度和效率,因为多个任务可以在同一时刻同时进行处理。在计算机领域,通常是通过多核处理器、GPU等技术来实现并行处理。并行处理的经典例子是在多核处理器上同时进行多个计算任务。多个程序或任务在同一时间段内同时执行的能力。

duehebfbf的博客 1279

Java 面试多线程基础精讲:核心概念与实战要点解析

本文系统梳理了Java多线程核心知识,涵盖线程生命周期状态转换、Java内存模型、线程实现方式及协作机制。重点分析了线程安全问题的根源与解决方案,包括synchronized同步、原子类使用和线程池调优策略。通过代码示例演示了生产者-消费者模型、线程安全计数器等典型场景,帮助开发者构建完整的多线程知识体系,为编写高效并发程序奠定基础。

jingpide9527的博客 1183

java多线程基础概念

程序:为了完成某一功能, (用某种语言编写的一组指令的集合),是一段静态的代码块 进程:程序的一次执行过程,是正在运行的程序,有着完整的生命周期,是资源分配的基本单位,由程序控制块(PCB)、程序段、数据段组成 线程:进程可以进一步细化为线程,是程序内部的一条执行路径,线程是独立调度和执行的最小单位 ,线程可以显著提高程序运行效率但也会带来安全隐患;具有以下优点:①提高cpu的利用率(不让CPU闲着)②提高用户响应(多线程可以使用户每一次操作都会立刻得到响应,单线程就要一个个来)③改善程序结,将长而复杂的代

wwwwwww31311的博客 1829
上一篇: 简明URI
下一篇: JAVA多线程基础篇 3、如何优雅结束一个线程
悟空学编程
博客等级 码龄12年 32粉丝 123原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悟空学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值