在Java多线程编程中,我们经常会用到wait()、notify()和notifyAll()方法,它们都属于Object类中用于锁的方法。其中notify()和notifyAll()方法都是用来唤醒等待线程的方法,但它们在本质上是有一定区别的。
一、notify()和notifyAll()方法的作用
notify()和notifyAll()都用于唤醒当前对象上等待的线程,使其进入就绪状态,以便争夺对象锁并执行。它们都必须在同步块或同步方法中被调用。
notify()方法会随机唤醒当前对象中等待的一个线程,如果当前对象中有多个线程等待,那么哪个线程被唤醒是不确定的。因此,notify()方法常用于“生产者-消费者”模型中,当生产者往队列中放入一个元素后,只需要唤醒一个消费者线程进行消费即可。
notifyAll()方法会唤醒当前对象中等待的所有线程,这些线程将被全部放入就绪状态,线程调度程序随后会从这些线程中选择一个作为下一个执行线程。因此,notifyAll()方法常用于同步操作完成后唤醒所有等待的线程。
二、notify()和notifyAll()方法的区别
notify()方法和notifyAll()方法的本质区别在于唤醒等待线程的方式不同。notify()方法仅仅是唤醒任意一个等待线程,而notifyAll()方法会唤醒所有等待线程。因此,notify()方法存在线程竞争的问题,可能会导致一些线程永远都无法被唤醒。而notifyAll()方法虽然效率较低,但它可以确保所有的等待线程都能够被唤醒。
示例一:
public class NotifyTest implements Runnable {
public synchronized void run() {
System.out.println(Thread.currentThread().getName() + " begin to wait...");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " has been notified...");
}
public static void main(String[] args) throws InterruptedException {
NotifyTest notifyTest = new NotifyTest();
Thread thread1 = new Thread(notifyTest, "Thread1");
Thread thread2 = new Thread(notifyTest, "Thread2");
Thread thread3 = new Thread(notifyTest, "Thread3");
thread1.start();
thread2.start();
thread3.start();
Thread.sleep(1000L);
synchronized (notifyTest) {
notifyTest.notify();
}
}
}
运行结果:
Thread1 begin to wait...
Thread2 begin to wait...
Thread3 begin to wait...
Thread1 has been notified...
在上面的示例中,我们创建了三个线程(Thread1、Thread2、Thread3),它们都调用notifyTest对象的wait()方法进行等待,然后主线程通过notify()方法唤醒对象上的一个线程。运行结果显示,只有Thread1被唤醒了,而Thread2和Thread3还在等待中,说明notify()方法只会唤醒其中的一个等待线程。
示例二:
public class NotifyAllTest implements Runnable {
public synchronized void run() {
System.out.println(Thread.currentThread().getName() + " begin to wait...");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " has been notified...");
}
public static void main(String[] args) throws InterruptedException {
NotifyAllTest notifyAllTest = new NotifyAllTest();
Thread thread1 = new Thread(notifyAllTest, "Thread1");
Thread thread2 = new Thread(notifyAllTest, "Thread2");
Thread thread3 = new Thread(notifyAllTest, "Thread3");
thread1.start();
thread2.start();
thread3.start();
Thread.sleep(1000L);
synchronized (notifyAllTest) {
notifyAllTest.notifyAll();
}
}
}
运行结果:
Thread1 begin to wait...
Thread3 begin to wait...
Thread2 begin to wait...
Thread2 has been notified...
Thread1 has been notified...
Thread3 has been notified...
在上面的示例中,我们创建了三个线程(Thread1、Thread2、Thread3),它们都调用notifyAllTest对象的wait()方法进行等待,然后主线程通过notifyAll()方法唤醒对象上的全部等待线程。运行结果显示,所有的等待线程都被唤醒了,且唤醒的顺序是不确定的。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java中的notyfy()和notifyAll()的本质区别 - Python技术站