您的位置:

Java中的wait方法详解

一、wait方法的概述

public final void wait() throws InterruptedException

wait方法是Object类中的一个方法,用于让当前线程进入等待状态,直到其他线程调用该对象的notify或notifyAll方法才可以唤醒它。调用wait方法必须使用在synchronized中,由于这个原因,wait方法只能够被在同步块内或者同步方法中调用,否则会抛出IllegalMonitorStateException。在调用wait方法时,线程会释放掉它所持有的锁,这样其他线程就可以进入到同步块或者同步方法中执行相应的代码。

二、wait方法的用法

wait方法常用于实现线程的互斥机制,通过wait和notify的配合使用,不同的线程可以协调运行。

wait方法的一般用法是:

  1. 获取要运行的线程对象
  2. 在同步块中调用线程对象的wait方法
  3. 在另一个线程中调用线程对象的notify或者notifyAll方法,通知要运行的线程唤醒

下面是一个使用wait和notify实现生产者消费者模型的示例代码:

public class ProducerConsumerExample {

    public static void main(String[] args) {
        Product product = new Product();
        new ProducerThread(product).start();
        new ConsumerThread(product).start();
    }

    static class ProducerThread extends Thread {
        private Product product;

        ProducerThread(Product product) {
            this.product = product;
        }

        @Override
        public void run() {
            while (true) {
                synchronized (product) {
                    while (product.getCount() >= Product.MAX_COUNT) {
                        try {
                            product.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    product.incrementCount();
                    System.out.println("生产了1个产品,当前产品数量为:" + product.getCount());
                    product.notifyAll();
                }
            }
        }
    }

    static class ConsumerThread extends Thread {
        private Product product;

        ConsumerThread(Product product) {
            this.product = product;
        }

        @Override
        public void run() {
            while (true) {
                synchronized (product) {
                    while (product.getCount() <= 0) {
                        try {
                            product.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    product.decrementCount();
                    System.out.println("消费了1个产品,当前产品数量为:" + product.getCount());
                    product.notifyAll();
                }
            }
        }
    }

    static class Product {
        private int count;
        static final int MAX_COUNT = 10;

        int getCount() {
            return count;
        }

        void incrementCount() {
            count++;
        }

        void decrementCount() {
            count--;
        }
    }
}

三、wait方法的注意事项

1、wait方法会释放锁

在执行wait方法之前,线程必须先获得锁,wait方法会释放该锁,使得其他线程可以获得这个锁。当wait方法返回后,当前线程又会重新获取这个锁。

2、wait方法可能会出现虚假唤醒

虚假唤醒是指,当一个线程调用了wait方法进入了等待状态,即使没有其他线程调用notify或notifyAll方法也有可能会被唤醒。对于此问题,可以在while循环中使用wait方法,循环条件为需要等待的条件。

3、线程调用interrupt方法可以中断wait方法

当一个线程在等待状态中,另一个线程调用了它的interrupt方法时,这个线程会抛出InterruptedException异常,从而退出等待状态。因此,在使用wait方法时要注意捕获InterruptedException异常。

四、总结

wait方法是实现线程等待和通知的重要手段,可以通过配合notify或notifyAll实现线程的协作运行。但是在使用wait方法时,需要考虑到线程的安全性,防止出错。