java面试题-sleep()和wait()有什么区别?
在Java多线程编程中,sleep()
和 wait()
是两个常用的方法,但它们有着不同的用途和行为。本教程将深入讨论这两个方法的区别,并通过详细的示例演示它们的使用。
1. sleep()
和 wait()
的基本区别
1.1 所属类和调用方式
sleep()
是Thread
类的静态本地方法;wait()
是Object
类的成员本地方法。
1.2 使用场景限制
sleep()
方法可以在任何地方使用;wait()
方法只能在同步方法或同步代码块中使用,否则抛出异常IllegalMonitorStateException
。
1.3 资源和锁的处理
sleep()
会休眠当前线程指定时间,释放 CPU 资源,但不释放对象锁,休眠时间到自动苏醒继续执行;wait()
方法放弃持有的对象锁,进入等待队列,只有当该对象被调用notify()
/notifyAll()
方法后才有机会竞争获取对象锁,进入运行状态。
1.4 异常处理
- JDK 1.8 中,
sleep()
和wait()
均需要捕获InterruptedException
异常。
2. 示例代码演示
2.1 示例场景
考虑以下场景,使用三个线程展示 sleep()
和 wait()
的不同行为:
RunnableImpl1
线程调用wait()
方法等待被唤醒;RunnableImpl2
线程调用sleep()
方法睡眠3秒后唤醒等待中的线程;RunnableImpl3
线程调用wait(1000)
方法等待1秒后自动苏醒。
2.2 示例代码
public class TestWaitSleep {
private static Object obj = new Object();
public static void main(String[] args) {
//测试 sleep()
//测试 RunnableImpl1 wait(); RunnableImpl2 notify()
Thread t1 = new Thread(new RunnableImpl1(obj));
Thread t2 = new Thread(new RunnableImpl2(obj));
t1.start();
t2.start();
//测试 RunnableImpl3 wait(long timeout)方法
Thread t3 = new Thread(new RunnableImpl3(obj));
t3.start();
}
}
class RunnableImpl1 implements Runnable {
private Object obj;
public RunnableImpl1(Object obj) {
this.obj = obj;
}
public void run() {
System.out.println("run on RunnableImpl1");
synchronized (obj) {
System.out.println("obj to wait on RunnableImpl1");
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("obj continue to run on RunnableImpl1");
}
}
}
class RunnableImpl2 implements Runnable {
private Object obj;
public RunnableImpl2(Object obj) {
this.obj = obj;
}
public void run() {
System.out.println("run on RunnableImpl2");
System.out.println("Sleeping for 3 seconds...");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj) {
System.out.println("notify obj on RunnableImpl2");
obj.notify();
}
}
}
class RunnableImpl3 implements Runnable {
private Object obj;
public RunnableImpl3(Object obj) {
this.obj = obj;
}
public void run() {
System.out.println("run on RunnableImpl3");
synchronized (obj) {
System.out.println("obj to wait on RunnableImpl3");
try {
obj.wait(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("obj continue to run on RunnableImpl3");
}
}
}
2.3 示例代码解释
RunnableImpl1
在同步块内调用wait()
方法,等待被唤醒;RunnableImpl2
调用sleep(3000)
方法后,唤醒了等待中的线程RunnableImpl1
;RunnableImpl3
在同步块内调用wait(1000)
方法,等待1秒后自动苏醒。
3. 执行结果
执行以上代码,将得到如下输出:
run on RunnableImpl2
Sleeping for 3 seconds...
run on RunnableImpl1
obj to wait on RunnableImpl1
run on RunnableImpl3
obj to wait on RunnableImpl3
obj continue to run on RunnableImpl3
notify obj on RunnableImpl2
obj continue to run on RunnableImpl1
以上结果清晰展示了 sleep()
和 wait()
在不同场景下的表现,对初学者理解这两个方法的差异有很大帮助。
4. 总结
本教程深入剖析了 sleep()
和 wait()
在Java中的区别,通过详细的示例代码演示了它们的使用场景和效果。理解这两个方法的不同,有助于在多线程编程中正确使用它们,提高程序的健壮性和效率。
正文到此结束
- 本文标签: Java 面试题
- 本文链接: https://www.jietongc.com/article/84
- 版权声明: 本文由大熊科技原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权