“sleep是所有线程都会休息是吗?”
简短回答:不是。
sleep
是让当前正在执行的线程暂停一段时间,其他线程不受影响。而 wait
是用于线程间通信,它会释放锁,并让当前线程等待。
下面我们进行详细的对比和解释。
1. Thread.sleep()
- 作用对象:当前执行的线程。哪个线程调用了
sleep()
,哪个线程就暂停。 - 锁的行为:在同步代码块或同步方法中调用
sleep()
时,它不会释放已经持有的对象锁。 - 唤醒条件:在指定的时间过后自动醒来,或者线程被中断(
InterruptedException
)。 - 方法来源:是
Thread
类的静态方法。 - 使用场景:用来暂停当前线程的执行,不需要考虑线程间的同步问题。
示例:
假设有两个线程 Thread-A 和 Thread-B。
- 如果 Thread-A 调用了
Thread.sleep(1000)
,那么只有 Thread-A 会休眠1秒钟。 - Thread-B 仍然可以继续运行,不受任何影响。
public class SleepExample {
public static void main(String[] args) {
Runnable task = () -> {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + " 开始工作");
try {
// 只有执行到这行代码的线程会休眠
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + " 结束工作");
};
Thread t1 = new Thread(task, "Thread-1");
Thread t2 = new Thread(task, "Thread-2");
t1.start();
t2.start();
}
}
输出可能是:
Thread-1 开始工作
Thread-2 开始工作
(等待约2秒后)
Thread-1 结束工作
Thread-2 结束工作
或者两个“结束工作”几乎同时打印,但它们各自都休眠了2秒。
2. Object.wait()
- 作用对象:同样是当前执行的线程。但它必须在一个同步上下文中被调用。
- 锁的行为:调用
wait()
会立即释放当前对象锁,这样其他线程才能获取该锁并执行。 - 唤醒条件:
- 其他线程调用同一个对象的
notify()
或notifyAll()
方法。 - 指定的超时时间到期(如果使用了带超时参数的
wait(long timeout)
)。 - 线程被中断。
- 其他线程调用同一个对象的
- 方法来源:是
Object
类的方法,任何Java对象都可以调用。 - 使用场景:用于线程间的协作和通信,通常与
notify()
/notifyAll()
配合使用,实现“等待-通知”机制。
示例:
public class WaitExample {
private static final Object lock = new Object();
public static void main(String[] args) {
Thread waitingThread = new Thread(() -> {
synchronized (lock) {
System.out.println("等待线程获取了锁,即将进入wait...");
try {
lock.wait(); // 释放锁,并等待
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("等待线程被唤醒,重新获取了锁。");
}
});
Thread notifyingThread = new Thread(() -> {
synchronized (lock) {
System.out.println("通知线程获取了锁,准备通知...");
lock.notify(); // 通知等待的线程
System.out.println("通知已发出。");
// 通知线程在退出同步块后才释放锁
}
});
waitingThread.start();
try { Thread.sleep(500); } catch (InterruptedException e) {} // 确保等待线程先执行
notifyingThread.start();
}
}
输出:
等待线程获取了锁,即将进入wait...
通知线程获取了锁,准备通知...
通知已发出。
等待线程被唤醒,重新获取了锁。
总结对比表格
特性 | Thread.sleep() |
Object.wait() |
---|---|---|
作用对象 | 当前线程 | 当前线程 |
锁的释放 | 不释放任何锁 | 释放当前对象锁 |
调用方式 | 静态方法:Thread.sleep(millis) |
实例方法:anyObject.wait() |
唤醒条件 | 时间到期或被中断 | 被 notify /notifyAll 、时间到期或被中断 |
所属类 | Thread 类 |
Object 类 |
使用前提 | 不需要在同步块中 | 必须在同步代码块或同步方法中(必须先持有锁) |
用途 | 单纯让当前线程暂停执行 | 线程间通信,实现等待/通知机制 |
结论
所以,回到你的问题:“sleep是所有线程都会休息是吗?”
绝对不是。 sleep
只会让调用它的那个当前线程休息,其他线程会继续争抢CPU时间片,正常运行。wait
也是让当前线程等待,但它更复杂,涉及到锁的释放和线程间的通信。
一个简单的比喻:
sleep
:就像你(当前线程)在工作时定了个闹钟,然后趴在桌子上小睡一会儿。你的办公桌(锁)别人还不能用,但公司的其他同事(其他线程)可以继续做他们自己的工作。wait
:就像你(当前线程)在等一个快递,你离开办公桌(释放锁)去休息室等着,并告诉前台(wait()
)。快递到了之后,前台通知你(notify()
),你才能回到你的办公桌(重新获取锁)继续工作。