本文主要是介绍2024年150道高频Java面试题(三十一),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
61. sleep() 和 wait() 有什么区别?
sleep()
和 wait()
方法在Java中被广泛用于线程控制,它们都可以让线程暂停执行一段时间,但它们之间存在一些重要的区别:
- 所属类:
sleep()
是Thread
类的静态方法。wait()
是Object
类的方法。
- 使用范围:
sleep()
可以在任何地方使用,因为它属于Thread
类。wait()
必须在同步上下文中调用,即必须在获取了对象锁的代码块中使用,通常用在对象的同步方法或同步代码块中。
- 释放锁:
sleep()
不会释放当前线程所持有的锁资源。wait()
会立即释放当前线程持有的锁资源,直到另一个线程调用同一个对象的notify()
或notifyAll()
方法来唤醒它。
- 精度:
sleep()
方法通常用于短时间等待,它能够指定具体的等待时间(毫秒或纳秒),并且能够较为准确地控制唤醒时间。wait()
方法没有参数,它通常用于线程间的通信,等待其他线程的通知,等待的时间是不确定的。
- 方法调用:
- 调用
sleep()
方法不需要当前线程拥有任何锁。 - 调用
wait()
方法必须在拥有对象的锁的情况下进行。
- 调用
- 唤醒方式:
sleep()
方法到达指定时间后自动唤醒。wait()
方法需要其他线程调用对象的notify()
或notifyAll()
来唤醒。
以下是 sleep()
和 wait()
的代码示例:
// sleep() 方法示例
Thread thread = new Thread(() -> {try {Thread.sleep(1000); // 休眠1秒} catch (InterruptedException e) {e.printStackTrace();}System.out.println("线程被唤醒");
});// wait() 方法示例
Object lock = new Object();
new Thread(() -> {synchronized (lock) {try {lock.wait(); // 等待} catch (InterruptedException e) {e.printStackTrace();}System.out.println("线程通过notify()被唤醒");}
}).start();// 在另一个线程中唤醒wait()的线程
new Thread(() -> {synchronized (lock) {lock.notify(); // 唤醒等待的线程}
}).start();
在使用 wait()
和 notify()
时,通常需要紧密协调以确保线程安全,而 sleep()
更适合于简单的定时等待场景。
62. notify() 和 notifyAll()有什么区别?
notify()
和 notifyAll()
是Java中用于线程同步的Object
类的方法,它们用于唤醒等待同一共享资源的线程。
notify()
方法:
- 它会随机选择一个在对象监视器上等待的线程,并通知该线程,使其从等待状态进入可运行状态。
- 选择哪个线程是由JVM决定的,并且是不可预测的。
- 如果没有线程在等待,
notify()
调用不会有任何效果。 - 在被通知的线程重新获得对共享资源的访问权限并退出同步块之前,其他线程仍然处于阻塞状态。
notifyAll()
方法:
- 它会通知所有在该对象监视器上等待的线程,使它们从等待状态进入可运行状态。
- 这样,所有等待的线程都有机会获取共享资源,并继续执行。
- 如果没有线程在等待,
notifyAll()
调用同样不会有任何效果。
以下是这两个方法的使用场景和区别的总结:
对比项 | notify() | notifyAll() |
---|---|---|
通知的线程数量 | 通知单个线程 | 通知所有等待的线程 |
使用场景 | 当只有一个线程需要被唤醒时,以避免不必要的上下文切换 | 当多个线程都在等待同一条件时,需要唤醒所有线程 |
效率 | 可能更高效,因为它不需要唤醒所有线程 | 可能导致上下文切换次数增多,但确保了所有等待线程都有机会运行 |
死锁风险 | 如果选择错误的线程可能会增加死锁的风险 | 适用于多个线程需要被唤醒的场景,降低了死锁的风险 |
以下是这两个方法的一个简单代码示例:
public class SharedObject {public synchronized void doSomething() {// 假设这里是需要共享资源的代码块// ...// 通知正在等待的线程(单个或所有)this.notify(); // 或者 this.notifyAll();}
}public class ThreadA extends Thread {private SharedObject sharedObject;public ThreadA(SharedObject sharedObject) {this.sharedObject = sharedObject;}@Overridepublic void run() {synchronized(sharedObject) {try {// 等待,直到被notify()或notifyAll()唤醒sharedObject.wait();} catch (InterruptedException e) {e.printStackTrace();}// 执行共享资源操作sharedObject.doSomething();}}
}
在以上代码中,notify()
和notifyAll()
可以在doSomething()
方法中互换使用,但它们的效果和适用场景会有明显的不同。
有帮助请点赞收藏呀~
领【150 道精选 Java 高频面试题】请 go 公众号:码路向前 。
这篇关于2024年150道高频Java面试题(三十一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!