当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


Java wait()和notifyall()的区别用法及代码示例


多线程是一种Java函数,它允许并发执行程序的两个或更多部分,以最大程度地利用CPU。这种程序的每个部分都称为线程。因此,线程是进程中的轻量级进程。Multi-threaded程序可能经常会遇到多个线程尝试访问相同资源并最终产生错误结果的情况。

因此,需要通过某种同步方法来确保在给定的时间点只有一个线程可以访问资源。Java提供了一种使用同步块创建线程并同步其任务的方法。 Java中的已同步块都用sync关键字标记。 Java中的同步块在某些对象上同步。在同一对象上同步的所有同步块一次只能在其中一个线程中执行。

稍后我们将讨论这些差异,让我们通过分别讨论以下内容来偷看它们之间的相互关系:

  1. wait()方法
  2. notifyAll()方法

1. wait()方法

在多线程中,两个线程可以使用wait()方法相互进行Inter-thread通信。期望更新的线程负责调用wait()方法,然后该线程将立即进入等待状态。 wait()方法存在于java.lang.Object类中,而不存在于Thread类中,因为线程可以在任何Java对象上调用此方法。要调用wait()方法,该线程应是该对象的所有者,即该线程应具有该对象的锁,即该线程应在同步区域内。因此,我们只能从同步区域调用wait()方法,否则我们将得到RuntimeException并声明IllegalMonitorStateException。如果线程在任何对象上调用wait()方法,它将立即释放该特定对象的锁并进入等待状态。



用法:

public  final void wait()

上面的方法使当前线程无限期地等待,直到为此对象调用notify()或notifyAll()。

public final native void wait( long microsecond)
public final void wait( long microsecond , int nanosecond)

使用以上两种方法,我们可以指定一个超时时间,之后线程将自动唤醒。我们可以使用notify()或notifyAll()方法在达到超时之前唤醒线程。

Note:Do remember that every wait() method throws InterruptedException which is a checked exception hence whenever we are using the wait() method compulsory we should handle this  InterruptedException either by try-catch or by throws keyword otherwise we will get compile-time  error.

2. notifyAll()方法

与wait()相似,在inter-thread通信中使用方法notifyAll()。线程负责执行更新,执行一些更新后,它负责调用notifyAll()方法,然后等待的线程将获得该通知,并使用更新的项目继续执行。 notifyAll()也存在于java.lang .Object类中。要在任何对象上调用notifyAll()方法,它们应该是该对象的所有者,即线程应位于同步区域内。因此,我们只能从同步区域调用notifyAll()方法,否则我们将得到RuntimeException并显示IllegalMonitorStateExceptiom。可以使用notifyAll()方法向特定对象的所有等待线程发出通知,但是即使有多个线程得到通知,但由于锁需要锁定的线程同时只有一个锁可用,因此执行将一一执行。

用法:

public final native void notifyAll()

实现方式:



在下面的示例中,我们创建了一个类“ myThread”,通常在程序中以这种方式命名该类,该程序扩展了Thread类,而Thread类本身又扩展了java.lang .Thread类。此类重写Thread类中可用的run()方法,线程在run()方法内开始其生命周期。在驱动程序类ThreadN中,我们创建一个对象并调用start方法以开始执行线程,并在ThreadN类中调用run()方法,我们同步了t1线程并将其置于等待状态。在myThread类内部,我们同步run方法,并在计算总和后使用notifyAll()方法向等待的线程发出通知。

Java

// Java Program to illustrate difference between 
// wait() and notifyAll() method 
  
// Importing java classes 
// Input output classes 
import java.io.*; 
import java.lang.*; 
// All utility classes from 
// java.util package 
import java.util.*; 
  
// Creating a thread in our myThread class 
// by extending the Thread class 
  
// Class 1 
// Helper class 
class myThread extends Thread { 
  
    // Declaring sum variable and 
    // initializing with zero 
    // as the current final sum 
    // as it is before iteration 
    int sum = 0; 
  
    // Method in helper class 
    // Declaring run method 
    public void run() 
    { 
  
        // Synchronizing this method 
        synchronized (this) 
        { 
            // Calculating the sum 
  
            // Display mwssage 
            System.out.println( 
                "child thread start calculation"); 
  
            // Iterating to calculate the sum 
            for (int i = 0; i <= 100; i++) 
  
                // Updating the current sum where 
                // last updated sum is final sum 
                sum += i; 
  
            // Display mwssage 
            System.out.println( 
                "child thread trying to give notification"); 
  
            // This keyword refers to current object itself 
  
            // Notifing the current waiting thread 
            // using notifyAll() method 
            this.notifyAll(); 
        } 
    } 
} 
  
// Class 2 
// Main class 
class ThreadN { 
  
    // Main driver method 
    public static void main(String[] args) 
        throws InterruptedException 
    { 
  
        // Creating a thread object 
        // in the main() method of  
        // our helper class above  
        myThread t1 = new myThread(); 
  
        // Starting the above thread created 
        // using the start() method 
        t1.start(); 
  
        // Synchronizing the thread 
        synchronized (t1) 
        { 
            // Display message 
            System.out.println( 
                "main thread trying to call wait method"); 
  
            // Putting the thread in the waiting state 
            // using the wait() method 
            t1.wait(); 
  
            // Display message 
            System.out.println("main thread get notify"); 
  
            // Print and display the sum 
            System.out.println(t1.sum); 
        } 
    } 
}
输出
main thread trying to call wait method
child thread start calculation
child thread trying to give notification
main thread get notify
5050

Now if the same program is run on terminal/CMD for custom user defined input then the hard coded input is shown below

Conclusion from the above program verifies the key differences between wait() and notifyAll() methods as follows: 

  1. wait()用于将线程置于等待状态,而notifyAll()方法唤醒特定对象的所有等待线程。
  2. 如果线程在任何对象上调用wait()方法,则立即释放该特定对象的锁,但是,如果线程在任何对象上调用notifyAll()方法,则也会释放该特定对象的锁,但不会立即释放。
  3. wait()notifyAll()方法不会引发任何InterruptedException,而方法会引发InterruptedException。

相关用法


注:本文由纯净天空筛选整理自mroshanmishra0072大神的英文原创作品 Difference Between wait() and notifyall() in Java。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。