sleep() 和 wait()

1. sleep() 方法

1.1 sleep() 的基本定义

Thread.sleep()Thread 类中的一个静态方法,用于使当前正在执行的线程进入休眠状态,也就是暂停执行一段时间。sleep() 方法有两个重载版本:

  • Thread.sleep(long millis): 让当前线程休眠指定的毫秒数。
  • Thread.sleep(long millis, int nanos): 让当前线程休眠指定的毫秒数和额外的纳秒数。

在指定的时间段内,线程保持阻塞状态,不占用CPU资源。休眠结束后,线程会重新进入就绪状态(Runnable),等待操作系统调度。

1.2 sleep() 的用法示例
public class SleepExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println("Thread is going to sleep...");
            try {
                Thread.sleep(2000); // 线程休眠2秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread has woken up.");
        });

        thread.start();
    }
}

在这个示例中,线程在输出“Thread is going to sleep…”后进入休眠状态,暂停执行2秒钟,之后继续执行并输出“Thread has woken up.”。

1.3 sleep() 的主要特性
  • 不释放锁:当线程调用 sleep() 时,它仍然持有着任何已获得的锁,因此其他线程无法访问这些锁保护的资源。
  • 不依赖同步sleep() 不需要与任何同步机制配合使用,任何线程都可以在任何地方调用 sleep()
  • 用于暂停线程执行sleep() 方法主要用于控制线程的执行节奏,比如定时任务、轮询机制等。

2. wait() 方法

2.1 wait() 的基本定义

wait()Object 类中的一个实例方法,用于使当前线程等待,直到其他线程调用该对象的 notify()notifyAll() 方法来唤醒它。wait() 方法通常与同步(synchronized)块结合使用,以协调多个线程对共享资源的访问。

wait() 方法有三个重载版本:

  • wait(): 让当前线程无限期地等待,直到它被通知(notify())。
  • wait(long timeout): 让当前线程等待指定的时间,如果在这段时间内没有被通知,线程会自动唤醒。
  • wait(long timeout, int nanos): 让当前线程等待指定的时间和纳秒数。
2.2 wait() 的用法示例
public class WaitExample {
    private static final Object lock = new Object();

    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            synchronized (lock) {
                System.out.println("Thread 1 is waiting...");
                try {
                    lock.wait(); // 线程1等待
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread 1 is resumed.");
            }
        });

        Thread thread2 = new Thread(() -> {
            synchronized (lock) {
                System.out.println("Thread 2 is notifying...");
                lock.notify(); // 唤醒等待的线程1
            }
        });

        thread1.start();
        try {
            Thread.sleep(1000); // 确保线程1先执行
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread2.start();
    }
}

在这个示例中,thread1lock 对象的监视器上等待,直到 thread2 调用 lock.notify() 来唤醒它。

2.3 wait() 的主要特性
  • 释放锁:当线程调用 wait() 时,它会释放它持有的锁,从而允许其他线程进入同步块并访问共享资源。
  • 依赖同步wait() 必须在同步块或同步方法中调用,调用 wait() 的线程必须持有对象的监视器(锁)。
  • 用于线程间通信wait() 通常用于线程间通信机制,例如生产者-消费者模型,在这种模式下,生产者和消费者线程之间需要通过 wait()notify() 进行协调。

3. sleep()wait() 的主要区别

3.1 所属类不同
  • sleep()sleep()Thread 类的静态方法,作用于当前正在执行的线程。
  • wait()wait()Object 类的实例方法,作用于调用 wait() 方法的对象的监视器。
3.2 锁的处理方式不同
  • sleep()sleep() 不会释放线程持有的锁。调用 sleep() 时,线程仍然持有锁,因此其他线程无法访问这些锁保护的资源。
  • wait()wait() 会释放当前线程持有的锁,以便其他线程可以获取这个锁,并继续执行同步块内的代码。
3.3 用途不同
  • sleep():用于简单的线程暂停,不涉及线程间的协作或通信。适合控制线程的执行节奏,如定时任务、间隔执行等。
  • wait():用于线程间的通信和协作,通常与 notify()notifyAll() 一起使用,以协调多个线程对共享资源的访问。
3.4 必须在同步块中使用的要求
  • sleep():可以在任何地方调用,不需要在同步块或同步方法中使用。
  • wait():必须在同步块或同步方法中调用,且调用线程必须持有该对象的监视器(锁)。
3.5 唤醒方式不同
  • sleep():线程在指定的时间结束后自动唤醒,或者可以被 interrupt() 中断唤醒。
  • wait():线程必须等待另一个线程调用 notify()notifyAll() 方法来唤醒,或者被 interrupt() 中断唤醒。

4. 实际应用场景

4.1 sleep() 的应用场景
  • 定时任务:在某些场景下,可能需要定期执行某些任务,例如每隔一段时间检查某些状态或执行某个动作。使用 sleep() 可以暂停线程执行,直到下一次执行时间。

  • 简单的等待机制:当一个线程需要等待一段时间再继续执行时,sleep() 是一种简单有效的方式。例如,在轮询某个资源的状态时,可以使用 sleep() 插入等待时间,避免频繁检查。

4.2 wait() 的应用场景
  • 生产者-消费者模型:在生产者-消费者模型中,生产者线程生成数据并将其放入缓冲区,而消费者线程从缓冲区中取出数据进行处理。如果缓冲区满了,生产者线程必须等待消费者取出数据后再继续生成。同样,如果缓冲区空了,消费者线程必须等待生产者生成数据。在这种情况下,wait()notify() 被用来协调生产者和消费者之间的操作。

  • 线程间的协作:在需要多个线程协调完成一个任务时,wait()notify() 非常有用。例如,在一个复杂的计算任务中,多个线程可能需要依赖前一个线程的结果才能继续执行。通过使用 wait() 使得线程等待,直到另一个线程完成某些操作并通知它继续执行。

5. 总结

在Java多线程编程中,sleep()wait() 都是控制线程执行的重要工具,但它们在功能、用途和行为上有着显著的区别:

  • sleep():用于暂停当前线程的执行,不涉及线程间的同步或通信。线程在休眠期间仍持有任何已获得的锁,但不会消耗CPU资源。适合用于定时任务或简单的等待机制。

  • wait():用于线程间的通信和协调,通常与同步机制结合使用。wait() 使线程进入等待状态,同时释放持有的锁,直到接收到 notify()notifyAll() 信号后被唤醒。适合用于复杂的线程协作场景,如生产者-消费者模型。

03-11
### Sleep 函数或命令的用法 #### 在编程语言中的 `sleep` 函数 在多种编程环境中,`sleep` 功能用于暂停程序执行一段时间。这可以用来实现定时操作或者控制并发任务的时间间隔。 对于 **Go** 编程语言而言,可以通过调用 `time.Sleep` 来让当前 goroutine 暂停指定时间,在这段时间里该 goroutine 不会占用 CPU 资源[^3]: ```go package main import ( "fmt" "time" ) func main() { fmt.Println("Start sleeping...") time.Sleep(2 * time.Second) // Pause for 2 seconds. fmt.Println("Wake up!") } ``` 而在 Java 中,则有类似的 Thread.sleep 方法来达到相同的效果[^2]: ```java public class Main { public static void main(String[] args) throws InterruptedException { System.out.println("Starting sleep..."); Thread.sleep(2000); // Pauses execution of this thread for two seconds. System.out.println("Awake now."); } } ``` #### 命令行下的 `sleep` 命令 当涉及到操作系统级别的脚本编写时,无论是 Linux/macOS 下的 bash 还是 Windows 的 CMD/PowerShell 都提供了相应的 `sleep` 工具以便于延迟特定毫秒数或是秒数再继续后续指令的操作[^1]。 - 对于 Unix-like 系统 (Linux macOS),可以直接使用如下形式的 shell 命令: ```bash echo 'Sleeping...' sleep 5s # pauses script execution for five seconds echo 'Slept well!' ``` - 对应地,在 PowerShell 或者传统的 Command Prompt 上面则采用稍微不同的语法结构: ```powershell Write-Output 'Going to sleep...' Start-Sleep -Seconds 5 # pauses powershell/cmd session for five seconds Write-Output 'Woke up.' ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Flying_Fish_Xuan

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

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

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

打赏作者

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

抵扣说明:

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

余额充值