百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

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个小秘密
你不知道的关于这只眯眼兔的6个小秘密

在你们忙着给熊本君做表情包的时候,要知道,最先在网络上引起轰动的可是这只脸上只有两条缝的兔子——兔斯基。今年,它更是迎来了自己的10岁生日。①关于德艺双馨“老艺...

2025-02-21 16:00 yuyutoo

取消回复欢迎 发表评论: