当多个线程可以共同访问同一资源时,为避免出现竞态条件,Java 提供了 wait-notify 方法。wait-notify 是 Object 类的两个方法,需要在同步代码块内被调用。wait 方法会使调用线程阻塞,直到另一个线程调用 notify 或 notifyAll 方法唤醒该线程。在该过程中,线程会释放锁。notify 方法则会随机唤醒等待中的一个线程(如果存在多个线程在等待同一个对象,则不能保证唤醒哪一个线程),notifyAll 则会唤醒所有等待线程。
下面是 wait-notify 方法的使用原则:
- wait 和 notify 方法只能在同步代码块内调用,并且必须通过同一对象的锁来调用。
- 在wait-notify使用过程中,必须加上synchronized,保证操作的原子性,防止数据冲突。
- 线程只有获得锁才可以进入wait状态或被唤醒,否则IllegalMonitorStateException。
- wait方法调用前必须先获取对象锁,否则抛出IllegalMonitorStateException异常。
- notify方法调用后会立即释放锁,而不是等待被唤醒的线程执行完才释放锁。
下面是一个示例,说明如何在Java中使用 wait-notify 方法:
public class ConsumerProducerExample {
public static void main(String[] args) {
//声明一个List作为缓冲器
List<Integer> buffer = new ArrayList<>();
//创建一个锁
Object lock = new Object();
//创建一个生产者
Runnable producer = new Producer(buffer, lock);
//创建一个消费者
Runnable consumer = new Consumer(buffer, lock);
//创建线程并启动
new Thread(producer).start();
new Thread(consumer).start();
}
}
class Producer implements Runnable {
private final List<Integer> buffer;
private final Object lock;
public Producer(List<Integer> buffer, Object lock) {
this.buffer = buffer;
this.lock = lock;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (lock) {
//如果缓冲器已满,生产者线程等待
while (buffer.size() >= 1) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//将生产的元素添加到缓冲器
buffer.add(i);
System.out.println("Producer produced " + i);
//唤醒消费者线程
lock.notify();
}
}
}
}
class Consumer implements Runnable {
private final List<Integer> buffer;
private final Object lock;
public Consumer(List<Integer> buffer, Object lock) {
this.buffer = buffer;
this.lock = lock;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (lock) {
//如果缓冲器为空,消费者线程等待
while (buffer.size() <= 0) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//从缓冲器中取出元素
int num = buffer.remove(0);
System.out.println("Consumer consumed " + num);
//唤醒生产者线程
lock.notify();
}
}
}
}
在这个示例中,一个生产者线程和一个消费者线程共享一个缓冲器。生产者生产元素,并将它们添加到缓冲器中。一旦缓冲器已满,生产者线程调用 wait 方法等待。消费者从缓冲器中取出元素并消费,如果缓冲器已空,那么消费者线程调用 wait 方法等待。生产者和消费者通过锁和 wait-notify 机制彼此协作,共享缓冲器。
还有一个示例:
public class WaitNotifyExample {
public void doWait() {
synchronized (this) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void doNotify() {
synchronized (this) {
this.notify();
}
}
}
在这个示例中,doWait 方法使调用线程进入等待状态,直到另一个线程调用与该对象关联的 doNotify 方法唤醒该线程。这两个方法都是同步的,因此需要在同步块内部调用它们。
总之,wait-notify 方法是Java中管理线程间通信的重要方式之一。当多个线程可以共同访问共享资源时,wait-notify 可以使线程协同工作,避免竞态条件。在使用 wait-notify 机制时,需要注意同步代码块以及获得锁的顺序,使其尽可能地符合 Java 的线程安全规定。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java如何正确的使用wait-notify方法你知道吗 - Python技术站