由于 system.out.println 语句导致运行线程延迟[重复]

2024-04-24

在下面的代码中,如果我在 for 循环内使用 sysout 语句,则代码将执行并在满足条件后进入循环内部,但如果我不在循环内使用 sysout 语句,则无限循环将继续进行,而不会进入 if 条件,即使if 条件满足..任何人都可以帮我找出确切的原因。只需一条 sysout 语句即可使 if 条件变为 true。为什么会这样呢?

代码如下:-

class RunnableDemo implements Runnable {
   private Thread t;
   private String threadName;

   RunnableDemo( String name){
       threadName = name;
       System.out.println("Creating " +  threadName );
   }
   public void run() {
      System.out.println("Running " +  threadName );
       for(;;)
       {
           //Output 1: without this sysout statement.
           //Output 2: After uncommenting this sysout statement
           //System.out.println(Thread.currentThread().isInterrupted());
           if(TestThread.i>3)
           {
               try {
                   for(int j = 4; j > 0; j--) {
                       System.out.println("Thread: " + threadName + ", " + j);
                   }
               } catch (Exception e) {
                   System.out.println("Thread " +  threadName + " interrupted.");
               }
               System.out.println("Thread " +  threadName + " exiting.");
           }
       }
   }
   
   public void start ()
   {
      System.out.println("Starting " +  threadName );
      if (t == null)
      {
         t = new Thread (this, threadName);
         t.start ();
      }
      
   }

}

public class TestThread {
       static int i=0;
   public static void main(String args[]) {
   
       RunnableDemo R1 = new RunnableDemo( "Thread-1");
      R1.start();
      try {
        Thread.sleep(10000);
    } catch (InterruptedException e) {
        
        e.printStackTrace();
    }
     
    i+=4;
     System.out.println(i);
   }   
}

无限循环中没有 sysout 语句的输出:-

在无限循环中使用 sysout 语句输出:-


这里的问题可以通过改变来解决

static int i=0;

to

static volatile int i=0;

制作一个变量volatile会产生许多复杂的后果,而我不是这方面的专家。因此,我将尝试解释我的想法。

变量i存在于你的主内存(RAM)中。但 RAM 速度很慢,因此您的处理器将其复制到更快(且更小)的内存:缓存。事实上有多个缓存,但这无关紧要。

但是,当两个不同处理器上的两个线程将它们的值放入不同的缓存时,当值发生变化时会发生什么?那么,如果线程 1 更改了缓存 1 中的值,线程 2 仍然使用缓存 2 中的旧值。除非我们告诉两个线程该变量i随时都可能发生变化,就像变魔术一样。这就是 volatile 关键字的作用。

那么为什么它与 print 语句一起工作呢?嗯,打印语句调用了很多幕后代码。其中一些代码很可能包含同步块或另一个易失性变量,它们(意外地)也会刷新i在两个缓存中。 (感谢 Marco13 指出了这一点)。

下次您尝试访问时i,你就得到了更新后的值!

PS:我在这里说的是 RAM,但它可能是两个线程之间最接近的共享内存,例如,如果它们是超线程的话,它可能是缓存。

这也是一个很好的解释(带图片!):

http://tutorials.jenkov.com/java-concurrency/volatile.html http://tutorials.jenkov.com/java-concurrency/volatile.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

由于 system.out.println 语句导致运行线程延迟[重复] 的相关文章

  • 如何在Android中将文件转换为base64(如.pdf、.text)?

    如何将 SD 卡文档 pdf txt 转换为 Base 64 字符串并将字符串发送到服务器 这个方法对我有用 String encodeFileToBase64Binary encodeFileToBase64Binary yourFile
  • 添加@Named时@SessionScoped不起作用

    考虑以下支持 bean import javax faces bean ManagedBean import javax faces bean SessionScoped ManagedBean SessionScoped public c
  • 在 Java 中将日期从 UTC 转换为 PST

    我需要将日期从 Google App Engine 本地服务器时区转换为 Java 中的太平洋时间 我尝试使用 Calendar calstart Calendar getInstance calstart setTimeZone Time
  • Thread.sleep vs Monitor.Wait vs RegisteredWaitHandle?

    以下项目有不同的目标 但我很有趣知道它们如何 暂停 问题 Thread sleep 它会影响系统性能吗 它是否会占用线程的等待时间 关于什么Monitor Wait 他们 等待 的方式有何不同 他们的等待会占用一个线程吗 关于什么Regis
  • Spring JSON序列化、Gson反序列化

    我目前在某些内部对象的反序列化方面遇到问题 在春天 我在使用输出之前初始化所有对象 ResponseBody 例如 这是一个响应 id 1 location id 1 extra location data id 2 location 1
  • 在这种情况下,我如何处理 Function 和省略号/可变参数?

    我的项目之一是抛出 lambda 表达式 https github com fge throwing lambdas 我的目标是简化潜在的使用 FunctionalInterfaces in Streams 其在流中使用的唯一 缺陷 是它们
  • Java中单击和双击的区别

    我搜索论坛并看到以下代码 public void mouseClicked MouseEvent e if e getClickCount 2 System out println and it s a double click wasDo
  • json文件格式的升级路径

    我们将 Java 应用程序的用户首选项存储在 JSON 文件中 使用Jackson http jackson codehaus org 随着我们继续开发该应用程序 我们将添加首选项 重命名首选项并删除过时的首选项 当用户将应用程序升级到下一
  • 将 Flash 文件上传与 JSF 集成

    我看到我们可以通过flash文件上传来上传多个文件 喜欢SWF上传 http code google com p swfupload or YUI上传器 http yuilibrary com yui docs uploader 是否可以将
  • 版本差异? Java 中的正则表达式转义

    看来正则表达式转义在不同版本的 Java 中的工作方式不同 在 Java openjdk 16 0 1 中编译工作正常 在 Java openjdk 11 0 11 中抛出此编译错误 test java 15 error illegal e
  • 无法为对象堆保留足够的空间

    每次尝试运行该程序时 我都会重复出现以下异常 VM初始化期间发生错误 无法为对象堆保留足够的空间 无法创建Java虚拟机 我尝试增加虚拟内存 页面大小 和 RAM 大小 但无济于事 我怎样才能消除这个错误 运行 JVM XX MaxHeap
  • 如何在 jax-ws 客户端中隐藏(可能)由 jax-ws 库引起的警告

    我正在使用 netbeans 在我的应用程序中生成 Web 服务客户端 我的程序使用 jax ws 库来设置调用 Web 服务的超时 出现问题是因为每当我启动这个程序时它都会生成很多这样的警告消息 2010 年 12 月 13 日下午 4
  • Windows:如何获取所有可见窗口的列表?

    无论如何都要使用相关技术重新标记 我不知道它们是什么 稍后我可能会提出更详细的问题 关于具体细节 但现在我正在尝试掌握 大局 我正在寻找一种方法来枚举 Windows 上的 真实可见窗口 我所说的 真正可见的窗口 就是指 用户所说的 窗口
  • AWS Lambda 和 S3 - 上传的 pdf 文件为空/损坏

    我有一个 Spring 应用程序 在 AWS Lambda 上运行 它获取文件并将其上传到 AWS S3 Spring控制器发送一个MultipartFile到我的方法 使用 Amazon API Gateway 将其上传到 AWS S3
  • 了解 Etc/GMT 时区

    Apple 在从 App Store 返回自动续订订阅收据时使用 Etc GMT 时区的理由是什么 Etc GMT 时区到底是什么 Java SDK 能理解这个时区吗 或者我是否必须使用其他第三方库 例如乔达时间 http www joda
  • 计算事件之间的天数 - Android

    我一直在研究 Android API 并一直在寻找一种方法来计算当前日期和未来日期之间的天数 我对 android 还很陌生 而且我已经有几年没有做过 java 了 计算这个最简单的方法是什么 Thanks 最简单的方法是使用乔达时间 ht
  • Java基于参数的同步(名为互斥锁/锁)

    我正在寻找一种根据接收到的参数来同步方法的方法 如下所示 public synchronized void doSomething name some code 我想要方法doSomething同步基于name参数如下 线程 1 doSom
  • 需要使用自定义类而不是在 Web 服务中生成(通过 wsimport)

    您能帮忙解决以下问题吗 当生成 WS 客户端代码 使用 wsimport ant 任务 时 所有类都会在与 Web 服务相同的包 例如 helloservice endpoint 中自动生成 例如如果我的网络服务有方法 公共节点 getNo
  • 指定不带组件的GridBagLayout的网格参数

    我试图帮助另一个用户 但遇到了一个问题 我想用 GridBagLayout 来做到这一点 c1 c2 c3 10 80 10 v v r1 B1
  • Spring Data JPA 存储库,具有规范、分页和标准 fetch-join

    我正在使用具有规范和分页功能的 Spring Data JPA 存储库实现实体列表的搜索 过滤服务 我正在尝试减少查询数量 n 1 问题 并使用条件获取机制获取嵌套数据 我有两个实体类 Entity Table name delegatio

随机推荐