您的位置:

Java中wait方法的使用

在Java中,wait方法是Object类的一个方法,用于等待某些条件的满足。当该方法被调用时,当前线程会被阻塞,直到其他线程调用该对象的notify或notifyAll方法,或者指定的等待时间到了才会继续执行。

一、wait方法的基本用法

wait方法必须在被同步的对象上调用,当线程调用wait方法时,它必须先获得该对象的锁,否则会抛出IllegalMonitorStateException异常。

synchronized(obj) {
    while(condition) {
        obj.wait();
    }
    // Some actions when condition is fulfilled
}

在上面的代码中,线程会无限期的等待,直到某些条件满足后被唤醒。wait方法必须包含在synchronized块中,这是因为线程在等待时会释放它所持有的锁,如果不在同步块中调用wait方法,就无法保证线程安全。

二、notify和notifyAll方法

Java中notify和notifyAll方法用于唤醒一个等待锁的线程或所有等待锁的线程。

notify方法随机唤醒一个等待该对象锁的线程,而notifyAll方法则唤醒所有等待该对象锁的线程。当某个线程调用notify或notifyAll方法时,被唤醒的线程只有在获取到锁之后才能继续执行。

synchronized(obj) {
    obj.notify(); // 或者 obj.notifyAll();
}

三、wait方法和notify方法的应用场景

wait和notify方法通常用于线程间的通信,例如:

1、等待一个线程完成任务后再继续执行

public class WaitNotifyDemo {
    public static void main(String[] args) {
        Object lock = new Object();

        Thread thread1 = new Thread(() -> {
            synchronized(lock) {
                System.out.println("Thread 1 started");
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread 1 finished");
            }
        });

        Thread thread2 = new Thread(() -> {
            synchronized(lock) {
                System.out.println("Thread 2 started");
                lock.notify();
                System.out.println("Thread 2 finished");
            }
        });

        thread1.start();
        thread2.start();
    }
}

在上面的代码中,线程1等待线程2发出notify信号后才继续执行。

2、线程之间的协作

public class ProducerConsumerDemo {
    public static void main(String[] args) {
        Object lock = new Object();
        List<Integer> buffer = new ArrayList<>();
        int maxSize = 10;

        Thread producer = new Thread(() -> {
            while (true) {
                synchronized (lock) {
                    // 如果缓冲区已满,则等待
                    while (buffer.size() == maxSize) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                    // 生产数据
                    int num = (int) (Math.random() * 100);
                    buffer.add(num);
                    System.out.println("Producer produced " + num);

                    // 唤醒消费者线程
                    lock.notifyAll();
                }
            }
        });

        Thread consumer = new Thread(() -> {
            while (true) {
                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.notifyAll();
                }
            }
        });

        producer.start();
        consumer.start();
    }
}

在上面的代码中,生产者线程和消费者线程共享同一个buffer,当缓冲区满了或为空时,就调用wait方法等待,直到其他线程调用notifyAll方法唤醒它们。

四、wait方法的超时等待

wait方法还可以指定等待时间,如果超过指定时间还没有收到notify信号,就会自动唤醒。

synchronized (obj) {
    long startTime = System.currentTimeMillis();
    long waitTime = 60000;
    long endTime = startTime + waitTime;
    while (condition && (System.currentTimeMillis() < endTime)) {
        obj.wait(endTime - System.currentTimeMillis());
    }
    // Some actions when condition is fulfilled
}

在上面的代码中,线程会在等待时间到达或者condition为false时继续执行。

五、wait方法和循环

使用wait方法时,通常需要在while循环中调用wait方法,而不是if语句。这是因为当notify信号返回后,线程可能仍然无法继续执行,此时线程会重新检查条件,如果条件满足,就继续执行,否则就继续等待。

synchronized (obj) {
    while (condition) {
        obj.wait();
    }
    // Some actions when condition is fulfilled
}

以上就是Java中wait方法的使用,可以通过wait和notify方法实现线程间的通信和协作。