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() 和同步机制 |