点击领取优惠~
901 字
5 分钟
请说说 sleep 和 wait 的区别?
请说说 sleep 和 wait 的区别?
答:sleep() 和 wait() 是 Java 中用于暂停当前线程的两个重要方法,sleep 是让当前线程休眠,不涉及对象类,也不需要获取对象的锁,属于 Thread 类的方法;wait 是让获得对象锁的线程实现等待,前提要获得对象的锁,属于 Object 类的方法。 它们之间的区别主要有以下几点:
所属类不同
- sleep() 方法专属于 Thread 类。
- wait() 方法专属于 Object 类。
锁行为不同
当线程执行 sleep 方法时,它不会释放任何锁。也就是说,如果一个线程在持有某个对象的锁时调用了 sleep,它在睡眠期间仍然会持有这个锁。
class SleepDoesNotReleaseLock {
private static final Object lock = new Object();
public static void main(String[] args) throws InterruptedException { Thread sleepingThread = new Thread(() -> { synchronized (lock) { System.out.println("Thread 1 会继续持有锁,并且进入睡眠状态"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Thread 1 醒来了,并且释放了锁"); } });
Thread waitingThread = new Thread(() -> { synchronized (lock) { System.out.println("Thread 2 进入同步代码块"); } });
sleepingThread.start(); Thread.sleep(1000); waitingThread.start(); }}输出结果:
Thread 1 会继续持有锁,并且进入睡眠状态Thread 1 醒来了,并且释放了锁Thread 2 进入同步代码块从输出中我们可以看到,waitingThread 必须等待 sleepingThread 完成睡眠后才能进入同步代码块。 而当线程执行 wait 方法时,它会释放它持有的那个对象的锁,这使得其他线程可以有机会获取该对象的锁。
class WaitReleasesLock {
private static final Object lock = new Object();
public static void main(String[] args) throws InterruptedException { Thread waitingThread = new Thread(() -> { synchronized (lock) { try { System.out.println("Thread 1 持有锁,准备等待 5 秒"); lock.wait(5000); System.out.println("Thread 1 醒来了,并且退出同步代码块"); } catch (InterruptedException e) { e.printStackTrace(); } } });
Thread notifyingThread = new Thread(() -> { synchronized (lock) { System.out.println("Thread 2 尝试唤醒等待中的线程"); lock.notify(); System.out.println("Thread 2 执行完了 notify"); } });
waitingThread.start(); Thread.sleep(1000); notifyingThread.start(); }}输出结果:
Thread 1 持有锁,准备等待 5 秒Thread 2 尝试唤醒等待中的线程Thread 2 执行完了 notifyThread 1 醒来了,并且退出同步代码块这表明 waitingThread 在调用 wait 后确实释放了锁。
使用条件不同
- sleep() 方法可以在任何地方被调用。
- wait() 方法必须在同步代码块或同步方法中被调用,这是因为调用 wait() 方法的前提是当前线程必须持有对象的锁。否则会抛出 IllegalMonitorStateException 异常。
唤醒方式不同
- sleep() 方法在指定的时间过后,线程会自动唤醒继续执行。
- wait() 方法需要依靠 notify()、notifyAll() 方法或者 wait() 方法中指定的等待时间到期来唤醒线程。
抛出异常不同
- sleep() 方法在等待期间,如果线程被中断,会抛出 InterruptedException。
- 如果线程被中断或等待时间到期时,wait() 方法同样会在等待期间抛出 InterruptedException。
我们来通过代码再感受一下 sleep() 和 wait() 在用法上的区别,先看 sleep() 的用法:
class SleepExample { public static void main(String[] args) { Thread thread = new Thread(() -> { System.out.println("线程准备休眠 2 秒"); try { Thread.sleep(2000); // 线程将睡眠2秒 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程醒来了"); });
thread.start(); }}再来看 wait() 的用法:
class WaitExample { public static void main(String[] args) { final Object lock = new Object();
Thread thread = new Thread(() -> { synchronized (lock) { try { System.out.println("线程准备等待 2 秒"); lock.wait(2000); // 线程会等待2秒,或者直到其他线程调用 lock.notify()/notifyAll() System.out.println("线程结束等待"); } catch (InterruptedException e) { e.printStackTrace(); } } });
thread.start(); }} 请说说 sleep 和 wait 的区别?