Java线程控制: sleep、yield、join深度解析
结论先行
- sleep:主动让出CPU但保持锁,适合控制执行节奏和优化CPU占用
- yield:建议让出CPU但无强制力,适用场景有限且效果不稳定
- join:通过等待机制实现线程顺序控制,底层基于wait实现锁释放
- 锁机制:sleep/yield不释放锁,join通过wait释放目标线程锁
- 性能优化:sleep(0)是实际开发中的高频优化技巧
文章持续更新,可以微信搜一搜「 半个脑袋儿 」第一时间阅读
一、sleep方法
核心特性
public static native void sleep(long millis) throws InterruptedException;
- 锁机制:保持当前线程持有的所有锁(不释放synchronized锁)
- CPU状态:从运行状态进入超时等待(TIMED_WAITING)
- 中断响应:可通过interrupt()中断等待
经典场景
- GC优化:在快速循环中插入sleep(0)
while (true) {
processBatch();
Thread.sleep(0); // 让出CPU给GC线程
}
- 降低CPU占用:批处理任务降频
for (int i = 0; i < 1_000_000; i++) {
processItem();
if (i % 100 == 0) {
Thread.sleep(1); // 每100次休眠1ms
}
}
实现原理
通过native方法实现操作系统级别的定时器调度,不同系统实现差异:
- Linux:基于nanosleep系统调用
- Windows:使用WaitForSingleObject
二、yield方法
核心特性
public static native void yield();
- 锁机制:保持当前线程持有的所有锁
- CPU状态:从运行状态回到就绪状态(RUNNABLE)
- 调度策略:依赖具体JVM实现(多数情况无效果)
适用场景
// 多线程并行执行相同任务
class ParallelTask implements Runnable {
public void run() {
while (!done) {
computeStep();
Thread.yield(); // 建议让出CPU
}
}
}
实现局限
- HotSpot VM中实际效果等同于短暂休眠(约1ms)
- 无法保证公平性,可能被调度器完全忽略
- 不同JVM实现差异大(如Zing VM有优化)
三、join方法
核心特性
public final synchronized void join() throws InterruptedException {
// 基于wait实现
while (isAlive()) {
wait(0);
}
}
- 锁机制:释放目标线程的监视器锁(通过wait)
- 等待方式:循环检测线程存活状态
- 中断处理:支持InterruptedException
典型用法
Thread worker = new Thread(task);
worker.start();
// 主线程等待worker完成
try {
worker.join();
} catch (InterruptedException e) {
handleInterruption();
}
// 继续执行后续逻辑
processResult();
方法对比表
| 特性 | sleep | yield | join |
|---|---|---|---|
| 锁释放 | 不释放 | 不释放 | 释放目标线程锁 |
| CPU状态 | TIMED_WAITING | RUNNABLE | WAITING |
| 中断响应 | 支持 | 不支持 | 支持 |
| 参数控制 | 精确时间控制 | 无 | 可设超时时间 |
| 使用频率 | 高频 | 极少 | 中频 |
最佳实践建议
- 避免滥用sleep:长时休眠应使用LockSupport.parkNanos()
- 替代yield方案:优先考虑wait/notify或Condition
- join超时保护:始终使用带超时的join方法
worker.join(5000); // 最多等待5秒
- 线程池整合:使用Future.get()替代join实现任务编排
- 响应中断:正确处理InterruptedException
通过合理组合使用这三个方法,可以实现精细化的线程控制,但需牢记:现代多线程开发更推荐使用java.util.concurrent包的高级API。
Java线程控制: sleep、yield、join深度解析的更多相关文章
- java多线程之yield,join,wait,sleep的区别
Java多线程之yield,join,wait,sleep的区别 Java多线程中,经常会遇到yield,join,wait和sleep方法.容易混淆他们的功能及作用.自己仔细研究了下,他们主要的区别 ...
- Java线程sleep,yield,join,wait方法详解
1.sleep() 当一个线程调用sleep方法后,他就会放弃cpu,转到阻塞队列,sleep(long millis)方法是Thread类中的静态方法,millis参数设定线程睡眠的时间,毫秒为单位 ...
- Java 线程控制
一.线程控制 和线程相关的操作都定义在Thread类中,但在运行时可以获得线程执行环境的信息.比如查看可用的处理器数目(这也行?): public class RunTimeTest { public ...
- Java中sleep,wait,yield,join的区别
sleep() wait() yield() join()用法与区别 1.sleep()方法 在指定时间内让当前正在执行的线程暂停执行,但不会释放“锁标志”.不推荐使用. sleep()使当前线程 ...
- Java多线程1:Java中sleep,wait,yield,join的区别
1.sleep()方法 在指定时间内让当前正在执行的线程暂停执行,但不会释放“锁标志”.不推荐使用. sleep()使当前线程进入阻塞状态,在指定时间内不会执行. 2.wait()方法 在其他线程调用 ...
- 并发编程——线程中sleep(),yield(),join(),wait(),notify(),notifyAll()区别
前言 今天简单的讲一讲线程中sleep(),join(),yield(),wait(),notify(),notifyAll()这些方法的使用以及区别. 不过在讲这些方法之前,需要简单的介绍一下锁池和 ...
- java线程控制、状态同步、volatile、Thread.interupt以及ConcurrentLinkedQueue
在有些严格的系统中,我们需要做到干净的停止线程并清理相关状态.涉及到这个主题会带出很多的相关点,简单的总结如下: 我们知道,在java中,有一个volatile关键字,其官方说明(https://do ...
- Java 线程池架构原理和源码解析(ThreadPoolExecutor)
在前面介绍JUC的文章中,提到了关于线程池Execotors的创建介绍,在文章:<java之JUC系列-外部Tools>中第一部分有详细的说明,请参阅: 文章中其实说明了外部的使用方式,但 ...
- java线程控制安全
synchronized() 在线程运行的时候,有时会出现线程安全问题例如:买票程序,有可能会出现不同窗口买同一张编号的票 运行如下代码: public class runable implement ...
- java线程学习之yield方法
yield方法是暂停当前正在执行的线程对象,并执行其他线程. 这是一个静态方法,一旦执行,它会使当前线程让出CPU.让出的cpu并不代表当前线程不执行了.当前线程让出CPU后,还会CPU资源的争夺,但 ...
随机推荐
- jar包启停shell脚本
jar包控制脚本1 #!/bin/bash export JAVA_HOME=/u01/java_home/jdk1.8.0_181 export APP_HOME=/u01/test export ...
- Doris建明细测试表,导入测试数据
分区.分桶.明细表 测试用户表 CREATE TABLE user_info( dt DATE, id varchar(36) NOT NULL DEFAULT '10', user_name var ...
- Luogu P2824 排序 题解 [ 紫 ] [ 线段树 ] [ 二分 ] [ adhoc ]
排序:二分线段树神仙好题. trick 我们可以二分值域,然后把大于等于它的数标记成 \(1\),其他标记为 \(0\)(有些题需要标记成 \(-1\) ),然后根据这个来 check 方案是否可行, ...
- mysql之我的第一个jdbc程序
package com.yeyue.lesson01; import java.sql.*; public class jdbcFirstDemo { public static void main( ...
- 使用browser-use进行数据爬取实战记录
前言 前面的文章介绍了browser-use的基本使用,今天带来的分享是使用browser-use进行一次数据爬取的实战(不过还是demo级别的). 使用到的三个玩法分别是使用自己的浏览器.定义输出结 ...
- 移动硬盘插入win10检测到却不显示盘符解决方法
1.开始菜单中的设置-----设备. 2.选择"蓝牙和其他设备" 3.在其他设备栏中就能看到检测到的移动硬盘,点击删除设备后重新插入移动硬盘即可在此电脑上显示盘符.
- MySQL2022.3.2
创建库 CREATE DATABASE STUDENT; 创建表 CREATE TABLE STU(SNO INT PRIMARY KEY,//主键SNM CHAR(2) NOT NULL,//不能为 ...
- 音视频SDK对比|K歌App中的实时合唱功能如何进行技术选型
摘要 在线K歌软件的开发有许多技术难点,需考虑到音频录制和处理.实时音频传输和同步.音频压缩和解压缩.设备兼容性问题等技术难点外,此外,开发者还应关注音乐版权问题,确保开发的应用合规合法. 前言 前面 ...
- 移动端 web 调试神器 - Eruda
移动端 web 调试神器 - Eruda 移动端 web 调试神器 - Eruda 基本使用 效果预览 核心步骤 安装依赖 yarn add vite-plugin-html -D # or npm ...
- 解决本地代理问题 git 或者 curl Failed to connect to 127.0.0.1 port 1087 after 8 ms: Connection refused
问题出现原因 git配置了代理 本地配置了代理 执行这个命令可以看到自己的代理设置: env | grep -I proxy 临时更改代理 在当前终端执行以下命令,就可以临时将代理取消掉 export ...