sleep 方法和 wait 方法有什么区别?

参考回答

Thread.sleep()wait() 都可以让线程暂停一段时间,但它们的功能和应用场景不同,主要区别如下:

  1. 作用范围不同
    • sleep()Thread 类的静态方法,只影响当前线程。
    • wait()Object 类的方法,必须与对象的同步锁一起使用。
  2. 是否释放锁
    • sleep() 不释放锁,线程睡眠期间仍然持有锁。
    • wait() 释放锁,使其他线程可以进入同步代码块。
  3. 恢复方式不同
    • sleep() 在指定时间到后自动恢复。
    • wait() 需要其他线程通过调用 notify()notifyAll() 显式唤醒。
  4. 使用场景
    • sleep() 用于让线程暂停执行一段时间,通常用于模拟延时或控制线程执行频率。
    • wait() 用于线程间通信,线程进入等待状态,直到其他线程发出通知。

详细讲解与拓展

1. Thread.sleep()

Thread.sleep() 是一个静态方法,用于让当前线程暂停指定的时间。线程暂停期间不会释放所持有的锁。

示例:使用 sleep() 控制线程暂停

public class SleepExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println("Thread starting...");
            try {
                Thread.sleep(2000); // 暂停2秒
            } catch (InterruptedException e) {
                System.out.println("Thread interrupted");
            }
            System.out.println("Thread resumed");
        });

        thread.start();
    }
}

关键点

  • 常用于线程延迟执行或模拟定时任务。
  • 不依赖锁,可以在任何地方使用。
  • 会抛出 InterruptedException,需要显式处理。

2. wait()

wait()Object 类的实例方法,必须与同步块 (synchronized) 一起使用。线程调用 wait() 后进入等待状态,同时释放锁,使其他线程可以访问同步代码块。

示例:使用 wait()notify() 实现线程通信

public class WaitNotifyExample {
    private static final Object lock = new Object();

    public static void main(String[] args) {
        Thread waitingThread = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("Thread waiting...");
                    lock.wait(); // 进入等待状态,释放锁
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread resumed");
            }
        });

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

        waitingThread.start();
        try {
            Thread.sleep(1000); // 确保waitingThread先运行
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        notifyingThread.start();
    }
}

关键点

  • wait() 使线程进入等待队列,并释放当前对象的锁。
  • 唤醒线程需要调用 notify()notifyAll()
  • 适用于线程间通信和协调。

区别对比

特点 Thread.sleep() wait()
类来源 Thread Object
作用范围 当前线程 同步代码块中的线程
是否释放锁 不释放锁 释放锁
恢复方式 时间到自动恢复 需要调用 notify()notifyAll()
是否需要锁 不需要锁 必须在同步块中使用
常见场景 延时执行、定时任务 线程间通信和同步

3. 使用场景的选择

适合使用 sleep() 的场景

  • 延时处理任务,例如在多线程中控制线程运行的间隔。
  • 模拟定时任务。
  • 模拟网络请求或其他耗时操作的延迟。

示例:定时任务

public class TimerExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            while (true) {
                System.out.println("Performing task...");
                try {
                    Thread.sleep(1000); // 每秒执行一次
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();
    }
}

适合使用 wait() 的场景

  • 线程间通信:一个线程需要等待另一个线程完成某个条件。
  • 实现生产者-消费者模型。

示例:生产者-消费者模型

import java.util.LinkedList;
import java.util.Queue;

public class ProducerConsumerExample {
    private static final Queue<Integer> queue = new LinkedList<>();
    private static final int CAPACITY = 5;

    public static void main(String[] args) {
        Thread producer = new Thread(() -> {
            int value = 0;
            while (true) {
                synchronized (queue) {
                    while (queue.size() == CAPACITY) {
                        try {
                            queue.wait(); // 队列满时等待
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    queue.add(value);
                    System.out.println("Produced: " + value);
                    value++;
                    queue.notifyAll(); // 通知消费者
                }
            }
        });

        Thread consumer = new Thread(() -> {
            while (true) {
                synchronized (queue) {
                    while (queue.isEmpty()) {
                        try {
                            queue.wait(); // 队列空时等待
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    int value = queue.poll();
                    System.out.println("Consumed: " + value);
                    queue.notifyAll(); // 通知生产者
                }
            }
        });

        producer.start();
        consumer.start();
    }
}

总结

使用场景 选择方法
线程需要暂停固定时间 使用 Thread.sleep()
线程间需要通信或等待 使用 wait()notify()
控制线程顺序或协调操作 使用 wait() 和同步机制

发表评论

后才能评论