42notify()和notifyall()有什么区别?(代码片段)

ynzj123 ynzj123     2023-03-20     602

关键词:

notify()和 notifyAll()有什么区别?

答:

两概念:Java中的 等待池、锁池。

  • 等待池:假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁后,进入到了该对象的等待池中。等待池中的线程不会去竞争该对象的锁。

  • 锁池:只有获取了对象的锁,线程才能执行对象的 synchronized 代码,对象的锁每次只有一个线程可以获得,其他线程只能在锁池中等待。

java中的锁池和等待池,地址

notify、notifyAll 的区别

  • 如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。

  • 当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。也就是说,调用了notify后只要一个线程会由等待池进入锁池,而notifyAll会将该对象等待池内的所有线程移动到锁池中,等待锁竞争。

  • 优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。

线程间协作:wait、notify、notifyAll,地址

综上,唤醒线程,另一种解释可以说是将线程由等待池移动到锁池,notifyAll调用后,会将全部线程由等待池移到锁池,然后参与锁的竞争,竞争成功则继续执行,如果不成功则留在锁池等待锁被释放后再次参与竞争。而notify只会唤醒一个线程。

所以,notify可能会导致死锁,而notifyAll则不会就很好解释。

原文链接: https://my.oschina.net/wxiwei/blog/1560818/print (概念)
原文链接: https://www.cnblogs.com/ConstXiong/p/12009144.html (拓展)

拓展:

测试代码

public class TestNotifyNotifyAll 
 
    private static Object obj = new Object();
    
    public static void main(String[] args) 
        
        //测试 RunnableImplA wait()        
        Thread t1 = new Thread(new RunnableImplA(obj));
        Thread t2 = new Thread(new RunnableImplA(obj));
        t1.start();
        t2.start();
        
        //RunnableImplB notify()
        Thread t3 = new Thread(new RunnableImplB(obj));
        t3.start();
        
        
//        //RunnableImplC notifyAll()
//        Thread t4 = new Thread(new RunnableImplC(obj));
//        t4.start();
    
    

 
 
class RunnableImplA implements Runnable 
 
    private Object obj;
    
    public RunnableImplA(Object obj) 
        this.obj = obj;
    
    
    public void run() 
        System.out.println("run on RunnableImplA");
        synchronized (obj) 
            System.out.println("obj to wait on RunnableImplA");
            try 
                obj.wait();
             catch (InterruptedException e) 
                e.printStackTrace();
            
            System.out.println("obj continue to run on RunnableImplA");
        
    

 
class RunnableImplB implements Runnable 
 
    private Object obj;
    
    public RunnableImplB(Object obj) 
        this.obj = obj;
    
    
    public void run() 
        System.out.println("run on RunnableImplB");
        System.out.println("睡眠3秒...");
        try 
            Thread.sleep(3000);
         catch (InterruptedException e) 
            e.printStackTrace();
        
        synchronized (obj) 
            System.out.println("notify obj on RunnableImplB");
            obj.notify();
        
    

 
class RunnableImplC implements Runnable 
 
    private Object obj;
    
    public RunnableImplC(Object obj) 
        this.obj = obj;
    
    
    public void run() 
        System.out.println("run on RunnableImplC");
        System.out.println("睡眠3秒...");
        try 
            Thread.sleep(3000);
         catch (InterruptedException e) 
            e.printStackTrace();
        
        synchronized (obj) 
            System.out.println("notifyAll obj on RunnableImplC");
            obj.notifyAll();
        
    

?

结果:仅调用一次 obj.notify(),线程 t1 或 t2 中的一个始终在等待被唤醒,程序不终止

run on RunnableImplA

obj to wait on RunnableImplA

run on RunnableImplA

obj to wait on RunnableImplA

run on RunnableImplB

睡眠3秒...

notify obj on RunnableImplB

obj continue to run on RunnableImplA
?

把 t3 注掉,启动 t4 线程。调用 obj.notifyAll() 方法

public class TestNotifyNotifyAll 
 
    private static Object obj = new Object();
    
    public static void main(String[] args) 
        
        //测试 RunnableImplA wait()        
        Thread t1 = new Thread(new RunnableImplA(obj));
        Thread t2 = new Thread(new RunnableImplA(obj));
        t1.start();
        t2.start();
        
//        //RunnableImplB notify()
//        Thread t3 = new Thread(new RunnableImplB(obj));
//        t3.start();
        
        
        //RunnableImplC notifyAll()
        Thread t4 = new Thread(new RunnableImplC(obj));
        t4.start();
    
    

?

结果:t1、t2线程均可以执行完毕

run on RunnableImplA

obj to wait on RunnableImplA

run on RunnableImplA

obj to wait on RunnableImplA

run on RunnableImplC

睡眠3秒...

notifyAll obj on RunnableImplC

obj continue to run on RunnableImplA

obj continue to run on RunnableImplA

notify和notifyall有什么区别

1/*2*文件名:NotifyDeadLockDemo.java3*版权:EnmuserTechnologiesCo.,Ltd.Copyright2016-20184*描述:<描述>5*修改人:enmuser6*修改时间:2018年2月24日7*修改单号:<修改单号>8*修改内容:<修改内容>9*10*/11packagenotify.deadLock;1213 查看详情

notify和notifyall有什么区别?(代码片段)

先说两个概念:锁池和等待池锁池:假设线程A已经拥有了某个对象(注意:不是类)的锁,而其它的线程想要调用这个对象的某个synchronized方法(或者synchronized块),由于这些线程在进入对象的synchronized方法之前必须先获得该对象的锁... 查看详情

通过使用 notify 代替 notifyAll 减少线程竞争

】通过使用notify代替notifyAll减少线程竞争【英文标题】:ReducethreadcompetitionbyusingnotifyinplaceofnotifyAll【发布时间】:2021-12-2106:42:17【问题描述】:我看到了这个自我实现的有界blockingqueue。对其进行了更改,旨在通过将notifyAll替换... 查看详情

Java - 何时使用 notify 或 notifyAll? [复制]

】Java-何时使用notify或notifyAll?[复制]【英文标题】:Java-whentousenotifyornotifyAll?[duplicate]【发布时间】:2011-02-1912:46:58【问题描述】:为什么java.lang.Object有两个通知方法——notify和notifyAll?似乎notifyAll至少完成了notify所做的所有事... 查看详情

为什么wait(),notify()和notifyall()必须在同步块或同步方法中调

 我们常用wait(),notify()和notifyAll()方法来进行线程间通信。线程检查一个条件后就行进入等待状态,例如,在“生产者-消费者”模型中,生产者线程发现缓冲区满了就等待,消费者线程通过消费一个产品使得缓冲区有空闲并... 查看详情

(转)为什么wait(),notify()和notifyall()必须在同步块或同步方法中调用

我们常用wait(),notify()和notifyAll()方法来进行线程间通信。线程检查一个条件后就行进入等待状态,例如,在“生产者-消费者”模型中,生产者线程发现缓冲区满了就等待,消费者线程通过消费一个产品使得缓冲区有空闲并通知... 查看详情

解释为什么wait()和notify(),notifyall()要放在同步块中

首先,wait()是释放锁的,因此wait()之前要先获得锁,而锁在同步块开始的时候获得,结束时释放,即同步块内为持有锁的阶段。那为什么要设计同步块呢?或者说没有同步块会怎样呢?  查看详情

java线程的wait(),notify()和notifyall()

wait(),notify()和notifyAll()方法用于在线程间建立关联.在对象上调用wait()将使线程进入WAITTING状态,直到其他线程对同一个对象调用notify()或notifyAll().在任何线程上,对一个对象调用wait(),notify()和notifyAll(),都需要先获得这个对象的锁,就... 查看详情

为什么多生产消费者要使用notifyall而不是notify(代码片段)

notify和notifyAll的区别?1.线程调用了wait()方法,便会释放锁,并进入等待池中,不会参与锁的竞争2.调用notify()后,等待池中的某个线程(只会有一个)会进入该对象的锁池中参与锁的竞争,若竞争成功,... 查看详情

wait和notify

...释放获取到的锁,直到别的线程调用了这个对象的notify或notifyAll方法。  notify:Object类的方法。作用是唤醒因调用wait挂起的线程,如果有过个线程,随机唤醒一个。  notifyAll:Object类的方法。作用是唤醒全部因调用wait挂起... 查看详情

javawait(),notify(),notifyall()的理解

这个三个函数来自Object类,众所周知它们是用于多线程同步的。然而,有个问题却一直没搞清楚,即notify()函数到底通知谁?《ThinkinginJAVA》中有这么一句话,当notify()函数因为某个特定锁被调用时,只有等待这个锁的任务才会被... 查看详情

多线程-wait/notify/notifyall

引言在Java中,可以通过配合调用Object对象的wait,notify和notifyAll来实现线程间的通信。在线程中调用wait方法,将阻塞带带其他线程的通知(其他线程调用notify或notifyAll)。在线程中调用notify或notifyAll将通知其他线程从wait方法处... 查看详情

为什么wait(),notify(),notifyall()必须在同步方法/代码块中调用?(代码片段)

在JAVA中,所有的对象都能够被作为‘监视器monitor’——指的是一个拥有一个独占锁,一个入口队列,和一个等待队列的实体entity。所有对象的非同步方法都能在任意时刻被任意线程调用,此时不需要考虑加锁的... 查看详情

关于wait,notify,notifyall,sleep方法的思考(代码片段)

...法,已经特别熟悉了.但是你知道吗为什么wait方法和notify,notifyAll定义在Object中,sleep定义在Thread中呢为什么wait方法和notify方法需要在同步代码块中使用(如果不在同步代码块使用会怎么样)wait,notify和sleep方法的异同为什么wait/notify/noti... 查看详情

使用reentrantlock和condition来代替内置锁和wait(),notify(),notifyall()(代码片段)

...内置锁,当使用内置锁的时候,我们可以使用wait()nitify()和notifyAll()来控制线程之间的协作,那么,当我们使用ReentrantLock的时候,我们怎么来处理线程之间的写作呢?JDK5.0为我们提供了Condition对象来替代内置锁的wait(),notify()和notifyAll()方... 查看详情

多线程(四)wait()notify()以及notifyall()(代码片段)

六、线程得等待和唤醒 1.wait()和notify()的简单示范publicclassWaitextendsThreadpublicsynchronizedvoidrun()System.out.println(getName()+"执行notify()");notify();publicstaticvoidmain(String[]args)Waitw=newWait();s 查看详情

wait(),notify(),notifyall()用来操作线程为什么定义在object类中?

这些方法存在于同步中;使用这些方法必须标识同步所属的锁;锁可以是任意对象,所以任意对象调用方法一定定义在Object类中。    Condition是在java1.5中才出现的,它用来替代传统的Object的wait()、notify()实现线程间... 查看详情

object的wait()notify()notifyall()方法和condition的await()signal()方法

wait()、notify()和notifyAll()是 Object类 中的方法从这三个方法的文字描述可以知道以下几点信息:1)wait()、notify()和notifyAll()方法是本地方法,并且为final方法,无法被重写。 2)调用某个对象的wait()方法能让当前线程阻塞... 查看详情