wait()和sleep()、yield()、jion()如何使用?
yuyutoo 2024-12-10 21:50 1 浏览 0 评论
wait()方法
- 定义和所属类:wait()方法是java.lang.Object类中的一个方法。这意味着在 Java 中,任何对象都可以调用这个方法。
- 作用机制:
- 当一个线程调用一个对象的wait()方法时,它会释放该对象的锁,然后进入等待状态。这个线程会一直等待,直到其他线程调用该对象的notify()或notifyAll()方法来唤醒它。例如,在一个生产者 - 消费者模型中,消费者线程在发现缓冲区为空时,可以调用wait()方法等待生产者生产数据。当生产者生产了数据并调用notify()方法后,消费者线程就会被唤醒,重新获取对象的锁并继续执行。
- 线程在wait()状态下是处于阻塞状态的一种,它会被放入对象的等待队列中,这个队列是和对象关联的,用于管理等待这个对象的线程。
- 使用场景:主要用于线程之间的协作和同步。比如在多线程访问共享资源(如共享数据结构)时,通过wait()和notify()可以实现对资源访问的有效控制,避免数据竞争和不一致性。
- 注意事项:调用wait()方法必须在同步代码块或者同步方法中,因为wait()方法会释放对象的锁,所以需要先获取锁才能释放。否则会抛出IllegalMonitorStateException异常。
- 示例代码:
import java.util.ArrayList;
import java.util.List;
class ProducerConsumerExample {
private List<Integer> buffer = new ArrayList<>();
private final int bufferSize = 5;
public synchronized void produce() {
while (buffer.size() == bufferSize) {
try {
// 如果缓冲区已满,生产者线程等待
wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
buffer.add(1);
System.out.println("Produced. Buffer size: " + buffer.size());
// 通知消费者线程可以消费了
notify();
}
public synchronized void consume() {
while (buffer.isEmpty()) {
try {
// 如果缓冲区为空,消费者线程等待
wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
buffer.remove(0);
System.out.println("Consumed. Buffer size: " + buffer.size());
// 通知生产者线程可以生产了
notify();
}
}
public class WaitExample {
public static void main(String[] args) {
ProducerConsumerExample example = new ProducerConsumerExample();
Thread producerThread = new Thread(example::produce);
Thread consumerThread = new Thread(example::consume);
producerThread.start();
consumerThread.start();
}
}
在上述代码中,生产者线程在缓冲区已满时调用wait()方法等待,消费者线程在缓冲区为空时也调用wait()方法等待。当生产者生产了一个数据后,通过notify()方法通知消费者线程,当消费者消费了一个数据后,通过notify()方法通知生产者线程。
sleep()方法
- 定义和所属类:sleep()方法是java.lang.Thread类中的一个静态方法。这意味着它是通过线程类来调用的,而不是像wait()那样通过对象来调用。
- 作用机制:
- 当一个线程调用Thread.sleep(long millis)方法时,它会使当前线程暂停执行指定的毫秒数。在这个期间,线程进入阻塞状态,但和wait()不同的是,它不会释放对象的锁(如果线程持有锁的话)。例如,如果一个线程在同步方法中调用sleep()方法,它依然会持有该方法所属对象的锁,其他线程无法访问这个同步方法,直到sleep()时间结束。
- 线程在sleep()结束后,会重新进入就绪状态,等待 CPU 调度,然后继续执行。
- 使用场景:用于让线程暂停一段时间,比如模拟延迟、定时任务等。例如,一个每隔一段时间就检查系统状态的线程,可以通过sleep()方法来实现定时检查。
- 注意事项:sleep()方法可能会抛出InterruptedException异常。这个异常通常在其他线程调用当前线程的interrupt()方法时抛出。所以在调用sleep()方法时,通常需要在try - catch块中处理这个异常。
- 示例代码:
public class SleepExample {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
try {
System.out.println("Thread started.");
// 线程暂停 3 秒
Thread.sleep(3000);
System.out.println("Thread resumed after 3 seconds.");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
thread.start();
}
}
在这个例子中,创建了一个线程,该线程在启动后先打印一条消息,然后调用sleep(3000)让线程暂停 3 秒,3 秒后继续执行并打印另一条消息。
yield()方法
- 定义和所属类:yield()方法是java.lang.Thread类中的一个静态方法。
- 作用机制:
- 当一个线程调用yield()方法时,它是在暗示调度器自己当前可以让出 CPU 资源。但是调度器是否会真正让当前线程暂停执行,这是不确定的。它可能会让当前线程暂停,然后重新进入就绪队列,等待下一次调度;也可能会忽略这个请求,让线程继续执行。
- 线程调用yield()方法后,会从运行状态转换到就绪状态,它不会像sleep()那样进入阻塞状态,也不会释放对象的锁(如果线程持有锁的话)。
- 使用场景:用于在多线程环境中,当一个线程完成了一部分任务,并且认为其他线程可能更需要 CPU 资源时,可以调用yield()方法来给其他线程机会执行。不过由于调度器的不确定性,它在实际应用中的效果可能不太好预测。
- 注意事项:yield()方法是一种启发式的方法,不能保证一定能达到预期的调度效果。在不同的操作系统和 JVM 实现中,yield()方法的行为可能会有所不同。
- 示例代码:
public class YieldExample {
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("Thread 1: " + i);
// 偶尔让出 CPU 资源
if (i % 2 == 0) {
Thread.yield();
}
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("Thread 2: " + i);
// 偶尔让出 CPU 资源
if (i % 3 == 0) {
Thread.yield();
}
}
});
thread1.start();
thread2.start();
}
}
在这个例子中,创建了两个线程,它们在循环中偶尔调用yield()方法尝试让出 CPU 资源,但实际效果取决于调度器的决策。
join()方法
- 定义和所属类:join()方法是java.lang.Thread类中的一个方法。
- 作用机制:
- 当在一个线程中调用另一个线程的join()方法时,当前线程会被阻塞,直到被调用join()方法的线程执行完毕。例如,有线程 A 和线程 B,在 A 中调用 B.join (),那么 A 会暂停执行,等待 B 完成后 A 才会继续执行。
- 使用场景:用于协调线程的执行顺序。比如在主线程中,如果需要等待某个子线程完成特定任务后再继续执行后续操作,就可以使用join()方法。
- 注意事项:join()方法可能会抛出InterruptedException异常。这个异常通常在当前线程被中断时抛出。所以在调用join()方法时,通常也需要在try - catch块中处理这个异常。
- 示例代码:
public class JoinExample {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
try {
System.out.println("Sub - thread started.");
// 模拟子线程执行一些耗时任务
Thread.sleep(2000);
System.out.println("Sub - thread finished.");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
thread.start();
try {
System.out.println("Main thread is waiting for sub - thread to finish.");
// 主线程等待子线程完成
thread.join();
System.out.println("Main thread continues after sub - thread finished.");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
在这个例子中,主线程启动一个子线程后,调用join()方法等待子线程完成。子线程在执行过程中会暂停 2 秒来模拟耗时任务,当子线程完成后,主线程才会继续执行。
异同点总结
- 相同点:
- 状态转换:wait()、sleep()、yield()和join()方法都会导致线程状态的改变。wait()和sleep()方法会使线程进入阻塞状态(wait()是无限等待或等待被唤醒,sleep()是限时等待),yield()方法会使线程从运行状态转换到就绪状态,join()方法会使当前线程进入阻塞状态,直到被调用join()方法的线程执行完毕。
- 影响执行顺序:它们都在一定程度上影响了线程的执行顺序。wait()是等待其他线程唤醒,sleep()是暂停一段时间后再继续执行,yield()是让出 CPU 资源(可能),join()是等待另一个线程完成,这些操作都会改变线程原本的执行顺序。
- 不同点:
- 所属类和调用方式:wait()是Object类的方法,需要通过对象来调用;sleep()和yield()、join()是Thread类的方法,sleep()和join()是实例方法,yield()是静态方法,sleep()是通过Thread.sleep()调用,yield()是通过Thread.yield()调用,join()是通过线程对象的join()方法调用。
- 锁的释放:wait()方法会释放对象的锁,而sleep()、yield()和join()方法不会释放对象的锁(如果线程持有锁的话)。
- 等待性质:wait()是等待其他线程通过notify()或notifyAll()来唤醒,是一种基于对象通知的等待;sleep()是基于时间的等待,线程会在指定时间后自动恢复;yield()是一种协作式的让出 CPU 资源,调度器是否接受这个请求是不确定的;join()是等待指定线程执行完毕的等待。
相关推荐
- 史上最全的浏览器兼容性问题和解决方案
-
微信ID:WEB_wysj(点击关注)◎◎◎◎◎◎◎◎◎一┳═┻︻▄(页底留言开放,欢迎来吐槽)●●●...
-
- 平面设计基础知识_平面设计基础知识实验收获与总结
-
CSS构造颜色,背景与图像1.使用span更好的控制文本中局部区域的文本:文本;2.使用display属性提供区块转变:display:inline(是内联的...
-
2025-02-21 16:01 yuyutoo
- 写作排版简单三步就行-工具篇_作文排版模板
-
和我们工作中日常word排版内部交流不同,这篇教程介绍的写作排版主要是用于“微信公众号、头条号”网络展示。写作展现的是我的思考,排版是让写作在网格上更好地展现。在写作上花费时间是有累积复利优势的,在排...
- 写一个2048的游戏_2048小游戏功能实现
-
1.创建HTML文件1.打开一个文本编辑器,例如Notepad++、SublimeText、VisualStudioCode等。2.将以下HTML代码复制并粘贴到文本编辑器中:html...
- 今天你穿“短袖”了吗?青岛最高23℃!接下来几天气温更刺激……
-
最近的天气暖和得让很多小伙伴们喊“热”!!! 昨天的气温到底升得有多高呢?你家有没有榜上有名?...
- CSS不规则卡片,纯CSS制作优惠券样式,CSS实现锯齿样式
-
之前也有写过CSS优惠券样式《CSS3径向渐变实现优惠券波浪造型》,这次再来温习一遍,并且将更为详细的讲解,从布局到具体样式说明,最后定义CSS变量,自定义主题颜色。布局...
- 你的自我界限够强大吗?_你的自我界限够强大吗英文
-
我的结果:A、该设立新的界限...
- 行内元素与块级元素,以及区别_行内元素和块级元素有什么区别?
-
行内元素与块级元素首先,CSS规范规定,每个元素都有display属性,确定该元素的类型,每个元素都有默认的display值,分别为块级(block)、行内(inline)。块级元素:(以下列举比较常...
-
- 让“成都速度”跑得潇潇洒洒,地上地下共享轨交繁华
-
去年的两会期间,习近平总书记在参加人大会议四川代表团审议时,对治蜀兴川提出了明确要求,指明了前行方向,并带来了“祝四川人民的生活越来越安逸”的美好祝福。又是一年...
-
2025-02-21 16:00 yuyutoo
- 今年国家综合性消防救援队伍计划招录消防员15000名
-
记者24日从应急管理部获悉,国家综合性消防救援队伍2023年消防员招录工作已正式启动。今年共计划招录消防员15000名,其中高校应届毕业生5000名、退役士兵5000名、社会青年5000名。本次招录的...
- 一起盘点最新 Chrome v133 的5大主流特性 ?
-
1.CSS的高级attr()方法CSSattr()函数是CSSLevel5中用于检索DOM元素的属性值并将其用于CSS属性值,类似于var()函数替换自定义属性值的方式。...
- 竞走团体世锦赛5月太仓举行 世界冠军杨家玉担任形象大使
-
style="text-align:center;"data-mce-style="text-align:...
- 学物理能做什么?_学物理能做什么 卢昌海
-
作者:曹则贤中国科学院物理研究所原标题:《物理学:ASourceofPowerforMan》在2006年中央电视台《对话》栏目的某期节目中,主持人问过我一个的问题:“学物理的人,如果日后不...
-
- 你不知道的关于这只眯眼兔的6个小秘密
-
在你们忙着给熊本君做表情包的时候,要知道,最先在网络上引起轰动的可是这只脸上只有两条缝的兔子——兔斯基。今年,它更是迎来了自己的10岁生日。①关于德艺双馨“老艺...
-
2025-02-21 16:00 yuyutoo
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- mybatis plus (70)
- scheduledtask (71)
- css滚动条 (60)
- java学生成绩管理系统 (59)
- 结构体数组 (69)
- databasemetadata (64)
- javastatic (68)
- jsp实用教程 (53)
- fontawesome (57)
- widget开发 (57)
- vb net教程 (62)
- hibernate 教程 (63)
- case语句 (57)
- svn连接 (74)
- directoryindex (69)
- session timeout (58)
- textbox换行 (67)
- extension_dir (64)
- linearlayout (58)
- vba高级教程 (75)
- iframe用法 (58)
- sqlparameter (59)
- trim函数 (59)
- flex布局 (63)
- contextloaderlistener (56)