在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方法实现线程间的通信和协作。