sleep 方法和 wait 方法有什么区别?
参考回答
Thread.sleep() 和 wait() 都可以让线程暂停一段时间,但它们的功能和应用场景不同,主要区别如下:
- 作用范围不同:
sleep()是Thread类的静态方法,只影响当前线程。wait()是Object类的方法,必须与对象的同步锁一起使用。
- 是否释放锁:
sleep()不释放锁,线程睡眠期间仍然持有锁。wait()释放锁,使其他线程可以进入同步代码块。
- 恢复方式不同:
sleep()在指定时间到后自动恢复。wait()需要其他线程通过调用notify()或notifyAll()显式唤醒。
- 使用场景:
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() 和同步机制 |