多线程是一种Java特性,它允许同时执行程序的两个或多个部分,以最大限度地利用 CPU。这种程序的每一部分都称为一个线程。因此,线程是进程中的轻量级进程。多线程程序可能经常会遇到多个线程试图访问相同资源并最终产生错误结果的情况。
所以需要通过某种同步方法来确保在给定的时间点只有一个线程可以访问资源。 Java提供了一种通过使用同步块来创建线程和同步它们的任务的方法。 Java中的同步块用 synchronized 关键字标记。 Java的同步块在某个对象上同步。在同一对象上同步的所有同步块一次只能有一个线程在其中执行。
我们稍后将讨论这些差异,让我们通过如下单独讨论它们来先睹为快:
- 等待()方法
- notifyAll() 方法
1. wait()方法
在多线程中,两个线程可以通过使用 wait() 方法相互进行线程间通信。等待更新的线程负责调用wait()方法,然后该线程将立即进入等待状态。 wait()方法存在于Java.lang.Object 类中而不是 Thread 类中,因为线程可以在任何Java对象上调用此方法。要调用任何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()类似,notifyAll() 方法用于线程间通信。线程负责执行更新,在执行一些更新后,它负责调用notifyAll()方法,然后等待线程将获得该通知并继续执行更新项目。 notifyAll()也存在于Java.lang .Object 类中。要在任何对象上调用notifyAll()方法,它们应该是该对象的所有者,即线程应该在同步区域内。因此,我们只能从同步区域调用notifyAll()方法,否则我们会得到 RuntimeException 说 IllegalMonitorStateExceptiom。可以使用notifyAll()方法向特定对象的所有等待线程发出通知,但即使多个线程收到通知但执行仍将一一执行,因为需要锁定的线程并且此时只有一个锁可用.
句法:
public final native void notifyAll()
执行:
在下面的示例中,我们创建了一个类“myThread”,通常它在程序中以这种方式命名,它扩展了我们的 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:
- 等待() 用于将线程置于等待状态,而notifyAll()方法唤醒特定对象的所有等待线程。
- 如果线程在任何对象上调用wait()方法,它会立即释放该特定对象的锁,但如果线程在任何对象上调用notifyAll()方法,它也会释放该特定对象的锁,但不会立即释放。
- wait()方法抛出 InterruptedException 而notifyAll()方法不抛出任何 InterruptedException。