目录
Thread#sleep() 方法和 Object#wait() 方法对比
共同点
- 两者都可以暂停线程的执行。
区别
-
锁的释放:
sleep()
方法不会释放锁。wait()
方法会释放锁。
-
用途:
wait()
通常用于线程间交互/通信。sleep()
通常用于暂停执行。
-
线程恢复:
wait()
方法调用后,线程不会自动苏醒,需要其他线程调用相同对象上的notify()
或notifyAll()
方法。sleep()
方法执行完成后,线程会自动苏醒,或者可以使用wait(long timeout)
超时后线程会自动苏醒。
-
方法定义:
sleep()
是Thread
类的静态方法。wait()
是Object
类的方法。
代码示例
java
// 示例:sleep() 方法
public class SleepExample {
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
try {
System.out.println("Thread t1 is going to sleep for 2 seconds.");
Thread.sleep(2000);
System.out.println("Thread t1 woke up.");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t1.start();
}
}
// 示例:wait() 方法
public class WaitExample {
private static final Object lock = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
synchronized (lock) {
try {
System.out.println("Thread t1 is waiting for lock.");
lock.wait();
System.out.println("Thread t1 got notified.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(() -> {
synchronized (lock) {
try {
Thread.sleep(1000); // Ensure t1 starts waiting first
System.out.println("Thread t2 is notifying lock.");
lock.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
}
}
为什么 wait() 方法不定义在 Thread 中?
wait()
是一个让获得对象锁的线程进入等待状态的方法,并会自动释放当前线程占有的对象锁。每个对象(Object
)都拥有一个内置的对象锁,因此需要操作对应的对象(Object
)而不是当前的线程(Thread
)。
源码解读
java
public final void wait(long timeoutMillis) throws InterruptedException {
if (timeoutMillis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
// Native method to put the thread in wait state
waitInternal(timeoutMillis);
}
wait()
方法在内部调用了本地方法 waitInternal
,这个设计是为了让线程等待并释放对象锁。
类似问题:为什么 sleep()
方法定义在 Thread
中?
因为 sleep()
是让当前线程暂停执行,不涉及对象锁的获取与释放,因此设计为 Thread
类的静态方法。
可以直接调用 Thread 类的 run 方法吗?
直接调用 run()
方法不会启动新的线程,只会在当前调用线程中执行 run()
方法的内容。因此,这并不能实现多线程的效果。
代码示例
java
public class RunVsStartExample {
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
System.out.println("Thread t1 is running.");
});
// 直接调用 run 方法,不会启动新线程
t1.run();
// 调用 start 方法,启动新线程
t1.start();
}
}
**总结:**调用 start()
方法会启动线程并使线程进入就绪状态,而直接执行 run()
方法则不会以多线程的方式执行。