Baeldung 翻译系列之Java并发基础:
Java中的concurrent包
Java中的Synchronized关键字
Future介绍
ThreadLocal介绍
Java线程的生命周期
如何杀掉一个Java线程
Java中的线程池介绍
实现Runnable接口还是继承Thread类
Java中的wait和notify方法
Runnable vs Callable
wait和sleep的区别
Thread.join方法介绍
Java中使用锁对象
ThreadPoolTaskExecutor中的corePoolSize和maxPoolSize
Java中的异步编程
1. 概览
在这篇简短的文章中,我们将会比对Java标准库中的sleep()
和wait()
方法,理解他们之间的相似处和不同点。
2. wait和sleep的一般区别
简单来说,wait()
是一个实例方法,用于线程同步。
它可以在任何对象上调用,因为它直接定义在java.lang.Object
上,但它只能从同步块中调用。它释放了对象上的锁,以便另一个线程可以跳入并获取锁。
另一方面,Thread.sleep()
是一个静态方法,可以从任何上下文中调用。Thread.sleep()
暂停当前线程并且不释放任何锁。
下面是这两个核心API的一个非常简单的初步演示:
private static Object LOCK = new Object();
private static void sleepWaitExamples()
throws InterruptedException {
Thread.sleep(1000);
System.out.println(
"Thread '" + Thread.currentThread().getName() +
"' is woken after sleeping for 1 second");
synchronized (LOCK) {
LOCK.wait(1000);
System.out.println("Object '" + LOCK + "' is woken after" +
" waiting for 1 second");
}
}
运行这个例子将产生以下输出:
线程main
在睡眠1秒后被唤醒
对象java.lang.Object@31befd9f
在等待1秒后被唤醒
3. 唤醒wait和sleep
当我们使用sleep()
方法时,线程会在指定的时间间隔后启动,除非它被中断。
对于wait()
,唤醒过程稍微复杂一些。我们可以通过在被等待的监视器上调用notify()
或notifyAll()
方法来唤醒线程。
当你想唤醒所有处于等待状态的线程时,应该使用notifyAll()
而不是notify()
。和wait()
方法本身一样,notify()
和notifyAll()
必须在同步上下文中调用。
例如,这是你可以等待的方式:
synchronized (b) {
while (b.sum == 0) {
System.out.println("Waiting for ThreadB to complete...");
b.wait();
}
System.out.println("ThreadB has completed. " +
"Sum from that thread is: " + b.sum);
}
然后,这是另一个线程如何通过在监视器上调用notify()
来唤醒等待的线程:
int sum;
@Override
public void run() {
synchronized (this) {
int i = 0;
while (i < 100000) {
sum += i;
i++;
}
notify();
}
}
运行这个例子将产生以下输出:
Waiting for ThreadB to complete…
ThreadB has completed. Sum from that thread is: 704982704
4. 总结
这是Java中wait
和sleep
语义的快速入门。
总的来说,我们应该使用sleep()
来控制一个线程的执行时间,使用wait()
进行多线程同步。当然,在理解基础知识之后,还有很多可以探索的内容。
评论区