多线程---线程的状态及常用方法

news2025/4/8 18:18:50

1. 线程的状态

        在Java程序中,一个线程对象通过调用start()方法启动线程,并且在线程获取CPU时,自动执行run()方法。run()方法执行完毕,代表线程的生命周期结束。

        在整个线程的生命周期中,线程的状态有以下六种:

New:新建状态,新创建的线程,此时尚未调用start()方法;

Runnable:运行状态,运行中的线程,已经调用了start()方法,线程正在或者即将调用run()方法;

Blocked:阻塞状态,运行中的程序在等待竞争锁时,被阻塞,暂不执行;

Waiting:等待状态,运行中的线程,因为join()等方法,进入等待;

Timed Waiting:计时等待状态,运行中的线程,因为执行sleep(等待时间)或join(等待时间)等方法,进入计时等待;

Terminated:终止状态,线程已经终止,因为run()方法执行完毕

 线程终止的原因有:
○线程正常终止:run()方法执行到return语句返回;
○线程意外终止:run()方法因为未捕获的异常导致线程终止;
○对某个线程的Thread实例调用stop()方法强制终止(不推荐使用);

2.线程的常用方法

2.1 线程的插队:join( )方法

作用:

        t.join()方法会使当前线程( 主线程 或者调用t.join()的线程 )进入等待池,并等待 线程t 执行完毕后才会被唤醒。此时,并不影响同一时刻处在运行状态的其他线程。

示例:
        myThread.join()被主线程调用,则主线程进入WAITING或者TIMED_WAITING(调用myThread.join(long millis))等待状态,主线程Main必须等子线程myThread执行完毕后才能继续执行。当子线程myThread执行完毕后,进入TERMINATED终止状态,会自动调用notifyAll()方法,唤醒主线程,主线程重新进入RUNNABLE运行状态,继续执行;

public class Test03_join {
	private static void printWithThread(String content) {
		System.out.println("[" + Thread.currentThread().getName() + "线程]" +content);
	}
	
	public static void main(String[] args) {
		printWithThread("开始执行main方法");
		Thread myThread = new Thread(new Runnable() {

			@Override
			public void run() {
				printWithThread("我在自定义的线程的run方法里");
				printWithThread("我马上要休息1秒钟,并让出CPU给别的线程使用.");
				
				try {
					Thread.sleep(1000);
					printWithThread("已经休息了1秒,又重新获得了CPU");
					printWithThread("我休息好了,马上就退出了");
				}catch (InterruptedException e) {
					e.printStackTrace();
			}
			
		}
		
	});
		try {
			myThread.start();
			printWithThread("我在main方法里面,我要等下面这个线程执行完了才能继续往下执行.");
			myThread. join();
			printWithThread("我在main方法里面,马上就要退出了.");
		}catch (InterruptedException e) {
			e.printStackTrace();

		}
	}
}

//运行结果:

[main线程]开始执行main方法
[main线程]我在main方法里面,我要等下面这个线程执行完了才能继续往下执行.
[Thread-0线程]我在自定义的线程的run方法里
[Thread-0线程]我马上要休息1秒钟,并让出CPU给别的线程使用.
[Thread-0线程]已经休息了1秒,又重新获得了CPU
[Thread-0线程]我休息好了,马上就退出了
[main线程]我在main方法里面,马上就要退出了.

join( )方法的实现原理

○join()方法的底层是利用wait()方法实现;
○join()方法是一个synchronized同步方法,当主线程调用 线程t.join( )方法时,主线程先获得了 线程t对象 的锁,随后进入join()方法,调用 线程t对象 的wait()方法,使主线程进入了 线程t对象 的等待池;
○等到 线程t 执行完毕之后,线程在TERMINATED终止状态的时候会自动调用自身的notifyAll()方法,来唤醒所有处于等待状态的线程:这个机制在隐藏在native本地方法中,由一个C++实现的方法ensure_join()函数实现。在该函数的尾部,执行了lock.notify_all(thread);,相当于调用了notifyAll()方法。

        综上所述:join()方法实际上是通过调用wait()方法, 来实现同步的效果的。
        例如:A线程中调用了B线程的join()方法,则相当于A线程调用了B线程的wait()方法,在调用了B线程的wait()方法后,A线程就会进入WAITING或者TIMED_WAITING等待状态,因为它相当于放弃了CPU的使用权。
        注意:join(0)的意思不是A线程等待B线程0秒,而是A线程等待B线程无限时间,直到B线程执行完毕:即join(0)=join();

        join()方法的源代码:

join( )方法和wait( )方法的区别

①定义的类不同

○sleep()方法是Thread类的静态方法

○wait()方法是Object类的方法

②锁的释放不同

sleep()方法不会释放任何锁,如果一个线程正在执行同步代码块或方法并且调用sleep()方法,它将继续持有该对象的锁,直到睡眠时间结束

wait()方法会释放当前线程持有的锁,允许其他线程访问同步代码块或方法。当线程被唤醒并重新竞争到锁后才能继续执行。

③调用位置不同

sleep()方法可以在任何地方调用,不需要在同步块或方法内;

wait()方法必须在同步块或方法中调用,因为它是 Object类的方法,通常在持有对象锁的情况下调用;

④唤醒机制不同

sleep()方法在指定的时间过后会自动恢复线程的执行;

wait() 方法需要被其他线程调用 notify()或 notifyA11()方法来唤醒,除非使用 wait(long timeout) 指定

超时时间,否则线程会一直等待直到被显式唤醒;

⑤异常抛出不同

sleep() 方法可能会抛出 InterruptedException(如果线程在睡眠期间被中断);

wait() 方法除了会抛出InterruptedException 以外,如果没有在同步代码块中调用,还会抛出 IllegalMonitorStateException

⑥作用目的

sleep()主要用于暂停线程的执行,可以用于定时任务、延迟执行等情况;

wait()主要用于线程间的通信和同步,如生产者消费者模型中等待资源可用或通知其他线程;

⑦sleep()和 wait()的主要区别在于锁的处理、调用环境和唤醒机制。用于线程之间的同步和通信。

sleep() 是一个简单的延时机制,而 wait()则

join( )方法和sleep( )方法的区别

两个方法都可以实现类似"线程等待"的效果,但是仍然有区别;
○join()是通过在内部使用synchronized + wait()方法来实现的,所以join()方法调用结束后,会释放锁
sleep()休眠没有结束前,不会释放锁

2.2 线程的中断:interrupt( )方法

        如果线程需要执行一个长时间任务,就可能需要能中断线程。中断线程就是其他线程给该线程发一个信号,该线程收到信号后结束执行run()方法,使得自身线程能立刻结束运行。
例如:假设从网络下载一个100M的文件,如果网速很慢,用户等得不耐烦,就可能在下载过程中点“取消”,这时,程序就需要中断下载线程的执行。
中断一个线程非常简单,只需要在其他线程中对目标线程调用interrupt()方法,目标线程需要反复检测自身状态是否是interrupted状态,如果是,就立刻结束运行。

interrupt( )方法的作用

        interrupt()方法的作用是设置该线程的中断状态为true,线程是死亡、还是等待新的任务或是继续运行至下一步,就取决于中断状态。线程会不时地检测这个中断状态值,以判断线程是否应该被中断(中断状态值是否为true)。

interrupt( )方法的原理

        interrupt()方法只是改变中断状态,不会像stop()中断一个正在运行的线程。支持线程中断的方法(Thread.sleep() 、join()、wait()等方法)就是在监视线程的中断状态,一旦发现线程的中断状态值被置为“true”,就会抛出线程中断的异常InterruptedException,给WAITING或者TIMED_WAITING等待状态的线程发出一个中断信号,线程检查中断标识,就会以退出WAITING或者TIMED_WAITING等待状态。

注意事项:

●线程被Object.wait(), Thread.join()和Thread.sleep()三种方法阻塞或等待,此时调用该线程的interrupt()方法,那么该线程将抛出一个 InterruptedException中断异常,从而提前终结被阻塞状态。
如果线程没有被阻塞或等待,调用 interrupt()将不起作用,直到执行到wait(),sleep(),join()等方法进入阻塞或等待时,才会抛出 InterruptedException异常

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

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

相关文章

文件翻译英文是什么软件?5款软件评测助你决策

在企业的日常运营中,文件翻译格式的多样性常常成为沟通效率的瓶颈。 从简单的文本文件到复杂的PDF文档,每一种格式都可能因为其特有的结构和布局,给翻译工作带来额外的挑战。 掌握翻译技巧需要时间和实践,以下是一些实用的翻译技…

数据增强又突破了!升级版“双杀”两大顶会,实现无痛涨点

数据收集和标注的艰难想必大家都有所体会,不仅耗时耗力还很贵,一般人顶不住。那怎么解决?你的“强”(数据增强)来了~ 数据增强作为一种正则化技术,可以帮助我们在有限的数据下,提高模型的性能。…

Vue.js魔法书:前端开发者的终极指南----指令篇续篇

​个人名片: 😊作者简介:一个为了让更多人看见许舒雅的宝贝的小白先生 🤡个人主页:🔗 许舒雅的宝贝 🐼座右铭:深夜两点半的夜灯依旧闪烁,凌晨四点的闹钟不止你一个。 &am…

linux 操作系统下的dhclient命令介绍和案例使用

linux 操作系统下的dhclient命令介绍和案例使用 dhclient 是 Linux 系统中用于动态主机配置协议(DHCP)客户端的命令。它的主要功能是从 DHCP 服务器获取网络配置,包括 IP 地址、子网掩码、默认网关和 DNS 服务器等信息 dhclient 命令概述 …

如何使用ssm实现校园二手交易平台的设计与开发+vue

TOC ssm641校园二手交易平台的设计与开发vue 研究背景与现状 时代的进步使人们的生活实现了部分自动化,由最初的全手动办公已转向手动自动相结合的方式。比如各种办公系统、智能电子电器的出现,都为人们生活的享受提供帮助。采用新型的自动化方式可以…

速通汇编(六)认识栈,SS、SP寄存器,push和pop指令的作用

一,栈 (一)栈的特点 栈是一种具有特殊访问方式的存储空间,特殊在于,进出这块存储空间的数据,“先进后出,后进先出” 由于栈的这个“先进后出”的特点,我们可以利用其来很好的操作内…

传输层协议 —— TCP协议(上篇)

目录 1.认识TCP 2.TCP协议段格式 3.可靠性保证的机制 确认应答机制 超时重传机制 连接管理机制 三次握手 四次挥手 1.认识TCP 在网络通信模型中,传输层有两个经典的协议,分别是UDP协议和TCP协议。其中TCP协议全称为传输控制协议(Tra…

Java毕业设计 基于SpringBoot和Vue自习室管理系统

Java毕业设计 基于SpringBoot和Vue自习室管理系统 这篇博文将介绍一个基于SpringBoot框架和Vue开发的自习室管理系统,适合用于Java毕业设计。 功能介绍 学生 登录 个人中心 修改密码 系统首页 自习室浏览 学生预约记录 管理员  登录 个人中心 修改密码 系统…

零信任安全架构--持续验证

随着网络安全威胁的不断演变,传统的“信任但验证”安全模式已无法应对现代复杂的攻击。零信任安全架构(Zero Trust Architecture, ZTA)应运而生,作为一种全新的安全理念,它彻底改变了企业的网络安全防护方式。核心思想…

file的判断和获取,创建和删除

常见成员方法 1.length 返回文件的大小(字节数量) 细节1:这个方法只能获取文件的大小,单位是字节如果单位我们要是M,G,可以不断的除以1024 细节2:这个方法无法获取文件夹的大小如果我们要获取一个文件夹的大小,需要把这个文件夹…

项目管理系统的期限提醒功能如何确保项目按时推进?

在竞争激烈的项目申报垂直领域,时间就是效率,效率关乎成败。每一个申报项目的截止日期都是一道不容错过的关卡,错过即意味着失去了宝贵的机会。为了确保项目能够按时推进,避免因时间管理不当而导致的延误,项目管理系统…

SpringCloud系列之一---搭建高可用的Eureka注册中心

前言 本篇文章主要介绍的是SpringCloud相关知识、微服务架构以及搭建服务注册与发现的服务模块(Eureka)以及Eureka集群。 GitHub源码链接位于文章底部。 什么是SpringCloud Spring Cloud 是一系列框架的有序集合。 它利用 Spring Boot 的开发便利性巧妙地简化了分布式系统基础设…

如何使用ssm实现基于web的物流配送管理系统的设计与实现+vue

TOC ssm646基于web的物流配送管理系统的设计与实现vue 第一章 绪论 1.1研究背景与意义 在科学技术水平还比较低下的时期,企业通常采用人工登记的方式对相关的物流配送信息进行记录,而后对这些信息记录进行管理和控制。这种采用纸质存储信息的管理模式…

平安养老险广东分公司:防范非法集资,守护消费者“钱袋子”

随着经济的不断发展,非法集资犯罪案件频频发生。非法集资案件受害人多,涉及资金广,犯罪手段多元化,涉案财物追缴困难等等。为提升金融消费者风险防范意识,保障其合法经济利益,今天我们一起来学习防范非法集…

利用条件编译解决vivado下verilog代码中ila与仿真的共存问题

vivado自带的仿真工具已经接近Modelsim的功能,且与原生开发环境的紧密结合,对仿真非常方便。 我的习惯是在实现工程中另外建一个仿真工程,保存仿真的testbench文件等,而实现工程中保存实际功能的源码文件。 这样仿真时会存在一个问…

PyQGIS开发 1 环境配置

PyQGIS 开发环境配置 1 安装QGIS QGIS官方下载地址 Windows环境下载对应版本的msi文件双击进行安装。 2 安装 PyCharm PyCharm官方下载地址 PyCharm官方提供专业版(收费)和社区版(免费)两个版本,自行选择下载、安…

Oracle EBS form个性化中调用带参数的存储过程或者函数

方式1 通过活动-消息 调用 这个方式的特点是会有一个消息弹框,不需要弹框时可以用方式2 方式2 通过 内置-执行过程 这个地方【变元】中的引用有点复杂,其中参数要用如下格式进行 #三个单引号||项目的表达式 ||${item.BLOCKNAME.FIELDNAME.value}|| #如…

从入门到精通,玩转Python的print函数(探索Python print函数的隐藏功能)

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 文章内容 📒📝 基础用法参数详解示例📝 高级用法自定义分隔符和结束符输出到文件追加模式📝 覆盖打印与进度条简单覆盖打印动态进度条示例代码⚓️ 相关链接 ⚓️📖 介绍 📖 刚开始学习编程时,我们接触到的第一个方…

运行npm install 时,卡在sill idealTree buildDeps没有反应

一直停留在sill idealTree buildDeps 解决方法 npm config set registry https://registry.npm.taobao.org 配置后用下面命令看是否配置成功 npm config get registry 如果配置还不好使 就执行下行的ssl npm set strict-ssl false 然后执行 npm install 成功执行

线程池的类型和状态

一、线程池的类型 1.通过Executors工具类创建的线程池对象 Executors.newFixedThreadPool(nThreads):固定线程数目的线程池; 核心线程数和最大线程数一致;只要非核心线程空闲,则立刻被回收;工作队列为无界队列。 Exe…