分享内容直达
全套面试题已打包2024最全大厂面试题无需C币点我下载或者在网页打开
引言:*
在多线程的世界里,wait()
、notify()
和 notifyAll()
是三位神奇的法师,它们掌握着线程间通信的秘密。想象一下,当一个线程在等待某个条件满足时,它就像是一位沉睡的骑士,而wait()
法师能够让它进入梦乡。一旦条件满足,notify()
或notifyAll()
法师就会唤醒它,让它继续它的征程。今天,我们就来揭开这三位法师的神秘面纱,探索它们的运行原理,了解它们在实战中的应用场景,并通过一段精彩的代码demo来体验它们的魔力。
一、运行原理
在Java中,wait()
、notify()
和 notifyAll()
方法是Object
类的原生方法,因此所有的对象都继承了它们。这些方法的工作原理基于一个叫做“等待池”的概念。当一个线程调用了wait()
方法,它就会被放入对象的等待池中,并释放锁。直到其他线程调用了notify()
或notifyAll()
方法,等待池中的线程才有可能被唤醒。
wait()
:使当前线程无限期等待,直到被其他线程唤醒(通过notify()
或notifyAll()
)或者被中断。notify()
:唤醒等待池中的一个线程。notifyAll()
:唤醒等待池中的所有线程。
二、应用场景
这些方法最常见的应用场景是条件同步。当一个线程需要等待某个条件成立时,它会调用wait()
方法进入等待状态。而当条件成立时,另一个线程会调用notify()
或notifyAll()
来通知等待的线程继续执行。
三、实战代码
让我们来看一个简单的例子,模拟一个生产者和消费者的场景:
public class ProducerConsumer {
final Object lock = new Object();
final int capacity = 10;
int count = 0;
public void produce() throws InterruptedException {
synchronized (lock) {
while (count == capacity) {
System.out.println("生产者等待...");
lock.wait();
}
count++;
System.out.println("生产了一个产品,当前库存:" + count);
lock.notifyAll();
}
}
public void consume() throws InterruptedException {
synchronized (lock) {
while (count == 0) {
System.out.println("消费者等待...");
lock.wait();
}
count--;
System.out.println("消费了一个产品,当前库存:" + count);
lock.notify();
}
}
public static void main(String[] args) throws InterruptedException {
ProducerConsumer demo = new ProducerConsumer();
Thread producer = new Thread(() -> {
for (int i = 0; i < 15; i++) {
demo.produce();
}
});
Thread consumer = new Thread(() -> {
for (int i = 0; i < 15; i++) {
demo.consume();
}
});
producer.start();
consumer.start();
producer.join();
consumer.join();
}
}
在这个例子中,我们有一个容量为10的库存。生产者线程每次生产一个产品前都会检查库存是否已满,如果已满,它会调用wait()
方法等待。消费者线程每次消费一个产品前都会检查库存是否为空,如果为空,它也会调用wait()
方法等待。当生产者生产了一个产品或者消费者消费了一个产品后,它们会调用notify()
或notifyAll()
来唤醒等待的线程。
四、结语
通过今天的探索,我们不仅理解了wait()
、notify()
和 notifyAll()
方法的运行原理,还通过一个实际的例子看到了它们在条件同步中的应用。这些方法就像是多线程编程中的魔法,能够让线程在等待和唤醒之间优雅地舞蹈。希望这篇文章能够帮助你更好地理解和使用这些强大的工具。如果你觉得这篇文章对你有帮助,别忘了点赞和评论哦!让我们一起在多线程的世界里,唤醒更多的可能!