当前位置: 首页 > 知识库问答 >
问题:

java - 为什么下面代码子线程无法中断run方法中的while循环?

胡永逸
2023-10-17

题目描述

如题

题目来源及自己的思路

子线程修改condition值为false,run方法while循环终止。

相关代码

粘贴代码文本(请勿用截图)

public class VisibilityDemo {    private static volatile boolean condition = true;    static void run() {        while (condition) {            // do something            System.out.println("...");        }        System.out.println("退出");    }    public static void main(String[] args) {        run();        new Thread(() -> {            condition = false;        }).start();    }}

你期待的结果是什么?实际看到的错误信息又是什么?

期待:打印一段".."后打印"退出"。
实际:持续打印"..",不会打印"退出"。

共有4个答案

翟修永
2023-10-17

run 不结束,不会执行到后面的 new Thread 。而 run 不会结束。

你可以把 run 也放到一个线程中去。

楚昀
2023-10-17

run死循环,不会走到new Thread

薛高澹
2023-10-17

主线程一直在循环里面,没法执行到new thread(),换下顺序试下.

弓泰
2023-10-17

这个问题是关于Java多线程中volatile关键字和while循环的逻辑的。

在Java中,volatile关键字保证了变量的可见性和顺序性。但是,这并不能确保在某个时间点,当线程A修改了某个volatile变量的值后,线程B可以立即看到这个修改。

在你的代码中,while (condition)是在run方法中执行的,而new Thread(() -> { condition = false; })是在main方法中启动的。虽然condition被声明为volatile,但是在run方法中的while循环并不能保证每次都从主内存中读取最新的condition值。也就是说,在这个循环中,可能还会读取到旧的condition值(即true),然后继续执行循环。

因此,即使子线程将condition设为false,主线程的while循环可能仍然无法看到这个修改,也就无法退出。

一种解决这个问题的方法是使用Thread.join()方法。这个方法会让当前线程等待子线程结束。这样,主线程就能在子线程修改condition之后再去检查这个值。以下是修改后的代码:

public class VisibilityDemo {    private static volatile boolean condition = true;    static void run() {        while (condition) {            // do something            System.out.println("...");        }        System.out.println("退出");    }    public static void main(String[] args) {        new Thread(() -> {            try {                Thread.sleep(1000); // 让子线程先运行一段时间            } catch (InterruptedException e) {                e.printStackTrace();            }            condition = false;        }).start();        run();        try {            Thread.sleep(1000); // 让主线程等待子线程结束        } catch (InterruptedException e) {            e.printStackTrace();        }    }}

这段代码中,主线程会等待子线程结束后再开始执行run方法中的while循环,这样可以确保在子线程修改了condition之后再去检查这个值。所以,这个代码的输出应该是先打印一段"...",然后打印"退出"。

 类似资料:
  • 我正在阅读这篇文章,关于从一个线程中断另一个线程的建议是 “”“如果正确实施,以下几种方法应该可以奏效。 您可以让两个线程定期检查一些常见的标志变量(例如,将其称为stopNow),并安排两个线程在完成时进行设置。(标志变量需要是volatile…或正确同步的。) 您可以让两个线程定期调用线程。isInterrupted()方法,查看它是否已被中断。然后每个线程都需要调用线程。完成后,在另一个上中

  • 我想优雅地关闭一个线程。然而,一旦关闭被启动,线程应该在结束通常的操作后执行一些关闭操作。 两个线程都使用Hibernate和/或等待,并处理中断异常,它们还在一个循环中处理任务,只需要几毫秒。所以我期望while循环结束,因为Thread.currentThread()。isInterrupted()变为“true”。 问题是,对于我的代码,有时我会得到日志“SHUTDOWN”,有时不会。此外,

  • 本文向大家介绍Java线程中start和run方法全面解析,包括了Java线程中start和run方法全面解析的使用技巧和注意事项,需要的朋友参考一下 自定义线程两种方法 自定义一个runnable接口的实现类,然后构造一个thread,即对thread传入一个runnable接口类。 new一个thread或者写个thread子类,覆盖它的run方法。(new 一个thread并覆盖run方法实

  • 很多次我看到在一些示例解决方案中,如果它说每秒停止线程,创建者在run方法中做了这样的事情: 所以在一个无限执行的while循环中。否则,我也看到了这一点: 为什么有时他们把睡眠方法放在一个循环中,而有时不放在一个循环中? 在一些解决方案中,代码的创建者将睡眠放在循环中,然后我删除了循环,代码停止工作。在其他不在循环中的情况下,我将其放入循环中,代码会导致错误。。。。为什么? 我怎么知道什么时候必

  • 问题内容: 我在ServerConnectionManager中有以下代码: 我在其他一些使用ServerConnectionManager的线程的run方法中有一些代码:让我们将此线程称为B 问题是我无法从ServerConnectionManager的run方法中调用ReceivedPacket上的任何方法。但是,我能够从此ServerConnectionManager线程的构造函数中调用re

  • 问题内容: 在Java线程中,“运行”方法不能引发“检查的异常”。我在Core Java(第1卷)书中遇到了这个问题。有人可以解释其背后的原因吗? 问题答案: 有人可以解释其背后的原因吗? 是的,因为您抛出的任何异常都会被JVM仔细忽略。因此,将其抛出可能是一个错误(除非您对该线程具有特定的异常处理程序,请参阅有关该文档的文档)。没有理由煽动潜在的错误行为。 或者举个例子。 编辑 为什么父线程不能