Java中的notyfy()和notifyAll()的本质区别

在Java多线程编程中,我们经常会用到wait()、notify()和notifyAll()方法,它们都属于Object类中用于锁的方法。其中notify()和notifyAll()方法都是用来唤醒等待线程的方法,但它们在本质上是有一定区别的。

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()的本质区别