在Java中等待,通知和NotifyAll方法示例

时间:2020-02-23 14:35:39  来源:igfitidea点击:

我们可能已经注意到对象类有三个名为Wain,Notify和NotifyAll的最终方法。
这些方法用于跨线程通信。
Java 5引入了执行者框架,该框架为我们和内部使用WATH线程通信,并且在内部使用等待,通知和NotifyAll,但我们仍然需要基本地了解这些方法以及使用WADE,Notify和NotifyAll在Java中运行的基本了解。

什么是等待,通知和NotifyAll方法?

等待,通知和NotifyAll方法用于允许通过访问公共对象或者其他术语彼此通信的线程,对象可以被认为是通过这些方法进行线程间通信的介质。
这些方法需要从同步上下文调用,否则它将抛出java.lang.illegalMonitorStateException。

同步块的一些背景:

  • 只有一个线程可以在同步块中的时间输入
  • 线程需要锁定对象以进入同步块。
  • 如果线程想要在同步块中输入,则线程A必须等待线程B释放它。

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

等待():

当我们在对象上调用wait方法,然后它告诉线程以放弃锁定并转到睡眠状态,除非以及在同一监视器中输入的其他线程并在其上调用通知或者通知或者NotifyAll方法。

通知():

在对象上调用通知方法时,它会唤醒等待该对象的一个线程。
因此,如果多个线程正在等待一个对象,它将唤醒其中一个。
现在你必须想知道它会醒来的哪一个。
它实际上取决于OS实现。

NotifyAll():

NotifyAll将唤醒等待该对象的所有线程,与通知仅唤醒其中一个。
唤醒首先唤醒,取决于线程优先级和OS实现。

让我们通过示例来理解:

1.创建一个名为book.java的类:它是一个线程在哪个线程的java bean类和调用等待和通知方法。

package org.igi.theitroad.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的类

此线程将等到其他线程调用通知方法,然后在完成其处理之后。
它首先将锁在Book对象上,并将从同步块调用。
所以,在此示例中,它将等待Bookwriter完成这本书。

package org.igi.theitroad.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的类

此类将通知线程(如果是在通知的情况下)正在等待Book对象。
它不会在调用通知时立即放弃锁定,它首先完成其同步块。
因此,在此示例中,BookWriter将完成该书并将其通知给BookReaders。

package org.igi.theitroad.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.igi.theitroad.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 igiReader=new BookReader(book);
  
  //BookReader threads which will wait for completion of book
  Thread johnThread=new Thread(johnReader,"John");
  Thread igiThread=new Thread(igiReader,"igi");
  
  igiThread.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()的情况下:当我们运行上面的程序时,我们将获取以下输出:

igi 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
igi: Book has been completed now!! you can read it

所以其中两个书籍线程(igi和John)正在等待书籍才能完成,所以他们称为Book.wait()。
一旦BookWrit者完成了IT书,它就称为Book.Notify()和igi线程启动并完成其处理。

在NotifyAll()的情况下:允许更改BookWriter类来调用Book.notifyAll()。

package org.igi.theitroad.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");
  
  }
 }
 
}

运行上面的程序时,我们将获取以下输出:

igi 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
igi: Book has been completed now!! you can read it

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