java中notify作用_notify的过去式

java中notify作用_notify的过去式用Java通知vsnotifyAllnotify和notifyAll方法之间有什么区别是棘手的Java问题之一,这很容易回答但是一旦访问者提出后续问题,你要么感到困惑,要么无法提供明确的答案?notify和notifyAll之间的主要区别在于notify方法只通知一个Thread,notifyAll方法将通知在该监视器上等待的所有线程或锁定。顺便说一句,这是你在各地阅读的内容,坦率地说,这句话…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

Java  notify   vs notifyAll

 

  • notify和notifyAll方法之间有什么区别是棘手的Java问题之一!

  • Condition 是个什么玩意?

提几个问题,从问题中去了解去学习:

  1. 他们之间有啥区别?
  2. 如果我使用notify(),将通知哪个线程?
  3. 我怎么知道有多少线程在等待,所以我可以使用notifyAll()?
  4. 如何调用notify()?
  5. 什么是这些线程等待被通知等?

我给点建议:建议使用jdk8里的lock包

  1. java.util.concurrent.locks下的Condition 他可以支持唤醒指定的线程。
  2.  他只是一个接口 具体实现类是在
    AbstractQueuedSynchronizer 也就是AQS框架里的 你可以自己继承他 或者使用 ReentrantLock里的newConditon()方法来获取

解决下问题:

  • Java中notify和notifyAll的区别
  1. Java提供了两个方法notify和notifyAll来唤醒在某些条件下等待的线程,你可以使用它们中的任何一个,但是Java中的notify和notifyAll之间存在细微差别,这使得它成为Java中流行的多线程面试问题之一。当你调用notify时,只有一个等待线程会被唤醒而且它不能保证哪个线程会被唤醒,这取决于线程调度器。虽然如果你调用notifyAll方法,那么等待该锁的所有线程都会被唤醒,但是在执行剩余的代码之前,所有被唤醒的线程都将争夺锁定,这就是为什么在循环上调用wait,因为如果多个线程被唤醒,那么线程是将获得锁定将首先执行,它可能会重置等待条件,这将迫使后续线程等待。因此,notify和notifyAll之间的关键区别在于notify()只会唤醒一个线程,而notifyAll方法将唤醒所有线程。
  •     何时在Java中使用notify和notifyAll
  1. 如果所有线程都在等待相同的条件,并且一次只有一个线程可以从条件变为true,则可以使用notify over notifyAll。
  2. 在这种情况下,notify是优于notifyAll 因为唤醒所有这些因为我们知道只有一个线程会受益而所有其他线程将再次等待,所以调用notifyAll方法只是浪费CPU。
  3. 虽然这看起来很合理,但仍有一个警告,即无意中的接收者吞下了关键通知。通过使用notifyAll,我们确保所有收件人都会收到通知

 

  • Java中通知和notifyAll方法的示例(后序demo示例代码 )
  1. 我已经汇总了一个示例来说明当我们在Java中调用notifyAll方法时如何通知所有线程,并且当我们在Java中调用notify方法时,只有一个Thread会被唤醒。
  2. 在这个例子中,如果boolean变量go为false,则三个线程将等待,记住boolean go是一个volatile变量,以便所有线程都能看到它的更新值。
  3. 最初三个线程WT1,WT2,WT3将等待,因为变量go为假,而一个线程NT1将变为真,并通过调用notifyAll方法通知所有线程,或通过调用notify()方法通知一个线程。在notify()调用的情况下,无法保证哪个线程会被唤醒,您可以通过多次运行此Java程序来查看它。
  4. 在notifyAll的情况下,所有线程都将被唤醒,但是它们将竞争监视器或锁定,并且将首先获得锁定的线程将完成其执行并且重置为false将迫使其他两个线程仍在等待。在该程序结束时,将有两个线程在等待,两个线程包括通知线程完成。程序不会终止,因为其他两个线程仍在等待,并且它们不是守护程序线程。
  5. 实例代码如下:以下是如何在Java中使用notify和notifyAll方法的完整代码示例。在解释了何时使用notify vs notifyAll方法,这个例子将阐明在Java中调用notify和notifyAll方法的效果。go!

 

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Java程序演示如何在Java和Java中使用notify和notifyAll方法
  *如何通知和notifyAll方法通知线程,哪个线程被唤醒等。
 */
public class NotificationTest {

    private volatile boolean go = false;

    public static void main(String args[]) throws InterruptedException {
        final NotificationTest test = new NotificationTest();
      
        Runnable waitTask = new Runnable(){
      
            @Override
            public void run(){
                try {
                    test.shouldGo();
                } catch (InterruptedException ex) {
                    Logger.getLogger(NotificationTest.class.getName()).
                           log(Level.SEVERE, null, ex);
                }
                System.out.println(Thread.currentThread() + " finished Execution");
            }
        };
      
        Runnable notifyTask = new Runnable(){
      
            @Override
            public void run(){
                test.go();
                System.out.println(Thread.currentThread() + " finished Execution");
            }
        };
      
        Thread t1 = new Thread(waitTask, "WT1"); //will wait
        Thread t2 = new Thread(waitTask, "WT2"); //will wait
        Thread t3 = new Thread(waitTask, "WT3"); //will wait
        Thread t4 = new Thread(notifyTask,"NT1"); //will notify
      
        //starting all waiting thread
        t1.start();
        t2.start();
        t3.start();
      
        //pause to ensure all waiting thread started successfully
        Thread.sleep(200);
      
        //starting notifying thread
        t4.start();
      
    }
    /*
     * wait and notify can only be called from synchronized method or bock
     */
    private synchronized void shouldGo() throws InterruptedException {
        while(go != true){
            System.out.println(Thread.currentThread()
                         + " is going to wait on this object");
            wait(); //release lock and reacquires on wakeup
            System.out.println(Thread.currentThread() + " is woken up");
        }
        go = false; //resetting condition
    }
  
    /*
     * both shouldGo() and go() are locked on current object referenced by "this" keyword
     */
    private synchronized void go() {
        while (go == false){
            System.out.println(Thread.currentThread()
            + " is going to notify all or one thread waiting on this object");

            go = true; //making condition true for waiting thread
            //notify(); // only one out of three waiting thread WT1, WT2,WT3 will woke up
            notifyAll(); // all waiting thread  WT1, WT2,WT3 will woke up
        }
      
    }
  
}

使用notify时的输出
Thread[WT1,5,main] is going to wait on this object
Thread[WT3,5,main] is going to wait on this object
Thread[WT2,5,main] is going to wait on this object
Thread[NT1,5,main] is going to notify all or one thread waiting on this object
Thread[WT1,5,main] is woken up
Thread[NT1,5,main] finished Execution
Thread[WT1,5,main] finished Execution

使用notifyAll时的输出
Thread[WT1,5,main] is going to wait on this object
Thread[WT3,5,main] is going to wait on this object
Thread[WT2,5,main] is going to wait on this object
Thread[NT1,5,main] is going to notify all or one thread waiting on this object
Thread[WT2,5,main] is woken up
Thread[NT1,5,main] finished Execution
Thread[WT3,5,main] is woken up
Thread[WT3,5,main] is going to wait on this object
Thread[WT2,5,main] finished Execution
Thread[WT1,5,main] is woken up
Thread[WT1,5,main] is going to wait on this object

强烈建议运行这个Java程序并理解它产生的输出并尝试理解它。除了死锁,竞争条件和线程安全之外,线程间通信是Java中并发编程的基础之一。

总结:

1)如果我使用notify(),将通知哪个线程?
无法保证,ThreadScheduler将从等待该监视器上的线程的池中选择一个随机线程。保证只有一个线程会被通知:(随机性)

2) 我怎么知道有多少线程在等待,所以我可以使用notifyAll()?
它取决于程序逻辑,在编码时需要考虑一段代码是否可以由多个线程运行。理解线程间通信的一个很好的例子是在Java中实现生产者 – 消费者模式。

3) 如何调用notify()?
Wait()和notify()方法只能从synchronized方法或块中调用,需要在其他线程正在等待的对象上调用notify方法。

4) 什么是这些线程等待被通知等?
线程等待某些条件,例如在生产者 – 消费者问题中,如果共享队列已满,则生产者线程等待,如果共享队列为空,则生成者线程等待。由于多个线程正在使用共享资源,因此它们使用wait和notify方法相互通信。

这就是Java中的notify和notifyAll方法之间的区别以及何时在Java中使用notify vs notifyAll。现在,应该能够理解并使用notify和notifyAll方法在Java程序中进行线程间通信。

补充下建议里的:lock包下的condition (demo里 是典型的生产者消费者模式》》》 使用的是condition来实现)

   final Lock lock = new ReentrantLock();
   //定义2组condition 对应生产者消费者
   final Condition notFull  = lock.newCondition(); 
  
   final Condition notEmpty = lock.newCondition(); 

   final Object[] items = new Object[100];
   int putptr, takeptr, count;
    //在put的时候 当数组已经满了的情况下 我让线程等待 不在容纳数据 当消费者已经消费了 触发了、、

//notfull.signal() 这时候通知生产者 我这变已经消费了 你那边可以试试了哈。 
   public void put(Object x) throws InterruptedException {
     lock.lock();
     try {
       while (count == items.length)
         notFull.await();
       items[putptr] = x;
       if (++putptr == items.length) putptr = 0;
       ++count;
       notEmpty.signal();
     } finally {
       lock.unlock();
     }
   }
//同上 相反的理解就是了。。。
   public Object take() throws InterruptedException {
     lock.lock();
     try {
       while (count == 0)
         notEmpty.await();
       Object x = items[takeptr];
       if (++takeptr == items.length) takeptr = 0;
       --count;
       notFull.signal();
       return x;
     } finally {
       lock.unlock();
     }
   }

 Condition因素出Object监视器方法(waitnotify 和notifyAll)为不同的对象,以得到具有多个等待集的每个对象,通过将它们与使用任意的相结合的效果Lock的实施方式。如果Lock替换synchronized方法和语句Condition的使用,则替换Object监视方法的使用。

条件(也称为条件队列或 条件变量)为一个线程提供暂停执行(“等待”)的手段,直到另一个线程通知某个状态条件现在可能为真。由于对此共享状态信息的访问发生在不同的线程中,因此必须对其进行保护,因此某种形式的锁定与该条件相关联。等待条件提供的关键属性是它以原子方式释放关联的锁并挂起当前线程,就像它一样Object.wait

一个Condition实例本质上绑定到一个锁。要获取Condition特定Lock 实例的实例,请使用其newCondition()方法。

举个例子,假设我们有一个支持puttake方法的有界缓冲区 。如果take在空缓冲区上尝试a ,则线程将阻塞直到某个项可用; 如果put在完整缓冲区上尝试a,则线程将阻塞,直到空间可用。我们希望 在单独的等待集中保持等待put线程和take线程,以便我们可以使用仅在缓冲区中的项或空间可用时通知单个线程的优化。

也就是说 可以创建多个condition 每组condition 对应你的具体的线程操作 当你

notFull.signalAll();的时候 你唤醒的也只是你这组condition里的等待线程 对于不在这组里的notEmpty是没有任何影响的 

现在 你是不是可以随心所欲的唤醒你想唤醒的线程了? 都看到这了 还不给个赞吗

 

 

 

 

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/195879.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • Java内存管理-JVM内存模型以及JDK7和JDK8内存模型对比总结(三)

    勿在流沙住高台,出来混迟早要还的。做一个积极的人编码、改bug、提升自己我有一个乐园,面向编程,春暖花开!上一篇分享了JVM及其启动流程,今天介绍一下JVM内部的一些区域,以及具体的区域在运行过程中会发生哪些异内存常! 其实也就对应了内存管理的第一篇中 JVM的第三个阶段,程序运行内存溢出。知识地图:一、概述Java的内存管理采用[自动内存管理]机制,因为这个自动管理机制,Ja…

  • 深度学习—3.Pytorch基础

    深度学习—3.Pytorch基础

  • mybatis自动生成代码插件idea_pro tools插件

    mybatis自动生成代码插件idea_pro tools插件IntellijIdeaMybatis插件主要有Mybatisplugin插件和Mybatistools插件。(一)Mybatisplugin插件主要功能有:提供Mapper接口与配置文件中对应SQL的导航编辑XML文件时自动补全根据Mapper接口,使用快捷键生成xml文件及SQL标签ResultMap中的property支持自动补全

  • STM32CubeMX介绍、下载与安装

    STM32CubeMX介绍、下载与安装推荐分享一个大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到人工智能的队伍中来!http://www.captainbed.net/strongerhuang本教程今年更新了部分内容:STM32CubeMX系列教程Ⅰ、写在前面相信很多人都知道STM32CubeMX这个工具,也是近年来开发STM32比较流行的一个工具。这个工具从两年…

  • 多线程CreateThread函数的用法

    多线程CreateThread函数的用法CreateThread当使用CreateProcess调用时,系统将创建一个进程和一个主线程。CreateThread将在主线程的基础上创建一个新线程,大致做如下步骤:1在内核对象中分配一个线程标

  • D-Link 路由 PCAnyWhere 端口映射

    D-Link 路由 PCAnyWhere 端口映射进入首页 设置固定DHCP服务器主机名称 IP地址(192.168.0.100)  MAC地址进入进阶设定  虚拟服务器建立新的虚拟服务器列表以下三项需建立并激活VirtualServerHTTP 192.168.0.100TCP80/80pcanywhere     192.168.0.100TCP5631/5631pcanywhere     192

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号