1. Java多线程
Java作为一门强大的编程语言,在多线程开发方面表现出色。Java中提供了多个线程的API,例如Thread类、Runnable接口、以及synchronized关键字等等,使得多线程编程变得更加容易。
2. wait()、notify()和notifyAll()的重要性
在多线程环境下,线程的调度和同步是非常重要的。而wait()、notify()和notifyAll()方法就是Java提供的类级别的方法,来帮助实现线程调度和同步。
2.1 wait()方法
wait()方法用于线程同步,使得一个线程处于等待状态,直到另一个线程调用该对象的notify()或notifyAll()方法唤醒该线程。
public synchronized void doWait() throws InterruptedException {
while(condition) {
wait();
}
}
上述代码中的doWait()方法,采用synchronized关键字修饰,表示此方法与该对象的实例相关,即将要获得该对象的锁。同时,在while循环中不断调用wait()方法,直到条件(condition)不成立,才会退出等待状态。
2.2 notify()方法
notify()方法调用时,会唤醒在此对象监视器上等待时间最长的一个线程,使其退出等待状态。如果有多个线程同时在此对象上等待,则只有一个能够被唤醒。
public synchronized void doNotify() {
condition = true;
notify();
}
上述代码中的doNotify()方法,同样采用synchronized关键字修饰。在方法中,将条件(condition)设置为true,并且调用notify()方法,唤醒在该对象上等待时间最长的线程。
2.3 notifyAll()方法
notifyAll()方法唤醒在此对象监视器上等待的所有线程。这个方法比notify()更加强大,但是也需要更加小心使用。
public synchronized void doNotifyAll() {
condition = true;
notifyAll();
}
上述代码中的doNotifyAll()方法同样采用synchronized关键字修饰,将条件(condition)设置为true,并且调用notifyAll()方法,唤醒所有在该对象上等待的线程。
3. wait()、notify()和notifyAll()的经典应用举例
在Java编程过程中,wait()、notify()和notifyAll()方法有非常经典的应用场景。例如在生产者-消费者的模型中,使用这三个方法来控制生产和消费的速度,避免生产过度或消费过度。
3.1 生产者-消费者模型
在生产者-消费者模型中,当生产者的缓存区已经满了,生产者需要等待消费者来消费一部分产品;而当消费者的缓存区空了,消费者需要等待生产者生产新的产品。这时候,就可以使用wait()、notify()和notifyAll()方法来控制生产和消费的速度。
下面是一个简单的生产者-消费者代码示例:
public class ProducerConsumer {
public static void main(String[] args) {
Queue<String> sharedQueue = new LinkedList<>();
int maxSize = 10;
Thread consumerThread = new Thread(new Consumer(sharedQueue, maxSize), "Consumer");
Thread producerThread = new Thread(new Producer(sharedQueue, maxSize), "Producer");
producerThread.start();
consumerThread.start();
}
}
class Producer implements Runnable {
private final Queue<String> sharedQueue;
private final int maxSize;
public Producer(Queue<String> sharedQueue, int maxSize) {
this.sharedQueue = sharedQueue;
this.maxSize = maxSize;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
synchronized (sharedQueue) {
while (sharedQueue.size() == maxSize) {
try {
sharedQueue.wait();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
sharedQueue.add("Product " + i);
sharedQueue.notifyAll();
}
}
}
}
class Consumer implements Runnable {
private final Queue<String> sharedQueue;
private final int maxSize;
public Consumer(Queue<String> sharedQueue, int maxSize) {
this.sharedQueue = sharedQueue;
this.maxSize = maxSize;
}
@Override
public void run() {
while (true) {
synchronized (sharedQueue) {
while (sharedQueue.isEmpty()) {
try {
sharedQueue.wait();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
System.out.println("Consumed: " + sharedQueue.remove());
sharedQueue.notifyAll();
}
}
}
}
在上述代码中,生产者和消费者在执行生产和消费的时候,都采用了synchronized关键字修饰,并且在while循环中使用了wait()和notifyAll()方法来控制生产和消费速度,避免生产过度或消费过度。
4. 总结
Java中的wait()、notify()和notifyAll()方法是Java多线程中非常重要的方法,用来实现线程的调度和同步。它们可以帮助我们控制并发,从而避免竞争条件等问题。生产者-消费者模型是wait()、notify()和notifyAll()方法经典的应用场景之一。