第五章 Java 中的 wait、notify 和 notifyAll 方法示例


您可能已经注意到 Object 类具有三个 final 方法,分别称为 wait、notify 和 notifyAll。这些方法用于线程间通信。Java 5 引入了执行器框架,它为您处理线程间通信,并在内部使用 wait、notify 和 notifyAll,但您仍然需要基本了解这些方法以及 java 中使用 wait、notify 和 notifyAll 的线程间通信如何工作。

什么是 wait 、 notify 和 notifyAll 方法?

wait 、 notify 和 notifyAll 方法用于允许线程通过访问公共对象来相互通信,或者换句话说,可以将 Object 视为通过这些方法进行线程间通信的媒介。这些方法需要从同步上下文中调用,否则会抛出 java.lang.IllegalMonitorStateException。

同步块的一些背景:

  • 在同步块中一次只能进入一个线程
  • 线程需要锁定对象才能进入同步块。
  • 如果线程 A 想要进入同步块,那么线程 A 必须等待线程 B 释放它。

让我们对这些方法有一些简要的了解:

wait():

当您在对象上调用 wait 方法时,它会告诉线程放弃锁定并进入睡眠状态,除非并且直到某个其他线程进入同一监视器并在其上调用 notify 或 notifyAll 方法。

notify():

当您在对象上调用 notify 方法时,它会唤醒等待该对象的线程之一。因此,如果多个线程正在等待一个对象,它将唤醒其中一个。现在你一定想知道它会唤醒哪一个。它实际上取决于操作系统的实现。

notifyAll() :

notifyAll 将唤醒等待该对象的所有线程,不像 notify 只唤醒其中一个。哪个将首先唤醒取决于线程优先级和操作系统实现。

让我们借助示例来理解它:

1. 创建一个名为 Book.java 的类: 这是一个 java bean 类,线程将在该类上执行并调用 wait 和 notify 方法。

package org.arpit.java2blog.thread;

public class Book {

String title;
boolean isCompleted;

public Book(String title) {
  super();
  this.title = title;
}

public String getTitle() {
  return title;
}
public void setTitle(String title) {
  this.title = title;
}
public boolean isCompleted() {
  return isCompleted;
}
public void setCompleted(boolean isCompleted) {
  this.isCompleted = isCompleted;
}

}

2. 创建一个名为 BookReader.java 的类

这个线程会一直等到其他线程调用notify方法,然后才会完成它的处理。它将首先锁定 book 对象,并从同步块中调用。因此在此示例中,它将等待 BookWriter 完成这本书。

ackage org.arpit.java2blog.thread;

public class BookReader implements Runnable{

Book book;

public BookReader(Book book) {
  super();
  this.book = book;
}

@Override
public void run() {
  synchronized (book) {
   System.out.println(Thread.currentThread().getName()+" is waiting for the book to be completed: "+book.getTitle());
   try {
    book.wait();
   } catch (InterruptedException e) {    
    e.printStackTrace();
   }
   System.out.println(Thread.currentThread().getName()+": Book has been completed now!! you can read it");
  }
}

}

3. 创建一个名为 BookWriter.java 的类

此类将通知正在等待书籍对象的线程(在通知的情况下)。它不会在调用 notify 后立即放弃锁,它首先完成其同步块。所以在这个例子中,BookWriter 将完成这本书并将其通知给 BookReaders。

package org.arpit.java2blog.thread;
public class BookWriter implements Runnable{

Book book;

public BookWriter(Book book) {
  super();
  this.book = book;
}

@Override
public void run() {
  synchronized (book) {
   System.out.println("Author is Starting book : " +book.getTitle() );
   try {
    Thread.sleep(1000);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   book.setCompleted(true);
   System.out.println("Book has been completed now");

   book.notify();
   System.out.println("notify one reader");

  }
}
}

4. 创建一个类ThreadInterCommunicationMain,java。 这是我们的主类,它将创建上述类的对象并运行它。

package org.arpit.java2blog.thread;

public class ThreadInterCommunicationMain {

public static void main(String args[])
{
  // Book object on which wait and notify method will be called
  Book book=new Book("The Alchemist");
  BookReader johnReader=new BookReader(book);
  BookReader arpitReader=new BookReader(book);

  // BookReader threads which will wait for completion of book
  Thread johnThread=new Thread(johnReader,"John");
  Thread arpitThread=new Thread(arpitReader,"Arpit");

  arpitThread.start();
  johnThread.start();

  // To ensure both readers started waiting for the book
  try {
   Thread.sleep(3000);
  } catch (InterruptedException e) {

   e.printStackTrace();
  }
  // BookWriter thread which will notify once book get completed
  BookWriter bookWriter=new BookWriter(book);
  Thread bookWriterThread=new Thread(bookWriter);
  bookWriterThread.start();

}

}

如果是 notify(): 当你运行上面的程序时,你会得到以下输出:

Arpit is waiting for the book to be completed: The Alchemist
John is waiting for the book to be completed: The Alchemist
Author is Starting book : The Alchemist
Book has been completed now
notify one reader
Arpit: Book has been completed now!! you can read it

所以在这里,两个 BookReader 线程(arpit 和 john)正在等待 book 完成,所以他们调用 book.wait()。一旦 BookWriter 完成它,它调用 book.notify() 并且 arpit 线程启动并完成它的处理。

在 notifyAll() 的情况下: 让我们将 BookWriter 类更改为调用 book.notifyAll()。

package org.arpit.java2blog.thread;

public class BookWriter implements Runnable{

Book book;

public BookWriter(Book book) {
  super();
  this.book = book;
}

@Override
public void run() {
  synchronized (book) {
   System.out.println("Author is Starting book : " +book.getTitle() );
   try {
    Thread.sleep(1000);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
   book.setCompleted(true);
   System.out.println("Book has been completed now");

   book.notifyAll();
   System.out.println("notify readers");

  }
}

}

当你运行上面的程序时,你会得到以下输出:

Arpit is waiting for the book to be completed: The Alchemist
John is waiting for the book to be completed: The Alchemist
Author is Starting book : The Alchemist
Book has been completed now
notify readers
John: Book has been completed now!! you can read it
Arpit: Book has been completed now!! you can read it

在 notifyAll() 的情况下,它会通知所有等待该对象的线程。


原文链接:https://codingdict.com/