在 system.exit() 之后线程仍然 运行
threads still running after system.exit()
我正在 Java 中学习多线程,并且正在试验线程。我想出了一种竞争条件代码(有点......请原谅这个菜鸟),其中 2 个线程循环工作(100 次)并竞相更改静态变量。目标是当一个线程第一次完成循环时(在时间片环境中或并行地 运行)打印变量的值并调用 system.exit(int status) 来终止程序!这是为了找出哪个线程赢得了比赛!
预期输出应为:nameOfTheThreadThatWonTheRace + "--" + valueOf'I'IncrementedInTheLoop
代码如下:
public class Nest
{
public static void main(String[] args) throws Exception
{
Thread r1 = new Thread(new Racer(),"R1");
Thread r2 = new Thread(new Racer(),"R2");
r1.start();
r2.start();
}
}
class Racer implements Runnable
{
public void run()
{
for(int i = 0; i <= 100; i++)
{
Value.value = Thread.currentThread().getName() + "--" + i;
}
Value.printValue();
System.exit(0);
}
}
class Value
{
static String value = null;
public static void printValue()
{
System.out.println(value);
}
}
但是实际输出不同(4 次运行):
R2--100
R2--100
R2--84
R2--100
R1--100
R1--100
R2--39
R2--100
我很困惑为什么 JVM 在任一线程到达 'System.exit(0)' 行后不停止? exit() 是否仅关闭主线程或整个 JVM,或者仍在执行的线程正在阻止 JVM 暂停?
另外请解释一下为什么要生成2行o/p?
For extra info:
Processor--> Intel® Core™ i5-7200U CPU @ 2.50GHz × 4
Ram--> 8GB
OS--> Fed27 workstation
(我还没有接触过 java.util.concurrent API 'yet' 但我知道我可以在那里以不同的方式管理线程..)
如果您能用正常的线程术语而不是指并发 API 来解释,我将不胜感激。
感谢您的帮助,再次原谅这个菜鸟:)
处理 System.exit(0)
需要时间,因此当调用它的线程正在等待操作系统终止并回收 运行 在不同内核上运行的代码时,就是运行ning在不同的内核上都能完成。这使它看起来像两个线程 "won the race".
请记住,在多线程环境中,一个线程无法显式控制另一个线程的时间;即使在系统关闭时。如果你想要那种控制,你需要明确地将它写入程序(例如通过让两个线程检查线程安全标志,以确定是否仍在竞争运行)。
调用 System.exit() 将关闭 JVM(请参阅 javadocs or the language specs)。
两个线程正在并行更新 Value 的静态成员。此类不安全更新的结果未定义。这就是您看到 strage 输出的原因。
一种解决方案是在 Racer class 中使用局部变量或字段,因为您不必在两个线程之间共享数据。此外,您甚至不需要它,因为您可以使用 Thread.currentThread().getName()
获取当前线程的名称
我想如果你在你的程序中添加一点日志记录,那么它可以帮助你理解到底发生了什么:
public void run()
{
for(int i = 0; i <= 100; i++)
{
if(i==100)
{
System.out.println(Thread.currentThread().getName() +" : before setting value 100th time : " + System.currentTimeMillis());
}
Value.value = Thread.currentThread().getName() + "--" + i;
if(i==100)
{
System.out.println(Thread.currentThread().getName() +" : after setting value 100th time : " + System.currentTimeMillis());
}
}
System.out.println(Thread.currentThread().getName() +" : before printing : " + System.currentTimeMillis());
Value.printValue();
System.out.println(Thread.currentThread().getName() +" : before exiting : " + System.currentTimeMillis());
System.exit(0);
}
class Value
{
static String value = null;
public static void printValue()
{
System.out.println(Thread.currentThread().getName() + " : value : " + value + " : " + System.currentTimeMillis());
}
}
首先,如果任何线程调用 System.exit(),那么 JVM 将终止(杀死所有线程!!!)。它不会等待任何线程执行,但会调用关闭挂钩、未调用的终结器等。因此,JVM 可能需要一些时间才能完成。您可以在这里阅读更多内容:
https://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#exit(int)
现在,您只提到了 4 运行 的输出。如果你再 运行 几次,我相信你会得到以下输出:
R2--100
这显然意味着 JVM 在另一个线程可以执行之前终止。
现在对于你的输出,说
R2--100 R2--100
两个线程都在 JVM 终止之前执行,很简单!
需要注意的一件事是两个线程的名称都是 R2。这是因为值变量是静态的并且在两个线程之间共享。由于竞争条件,在 R2 可以打印该值之前,它已由 R1 设置。如果您添加我建议的日志记录,您可以看到这一点。
参见下面的示例输出:
R2 : before setting value 100th time : 1517579707689
R2 : after setting value 100th time : 1517579707690
R1 : before setting value 100th time : 1517579707689
R1 : after setting value 100th time : 1517579707691
R2 : before printing : 1517579707691
R1 : before printing : 1517579707692
R2 : value : R1--100
R1 : value : R1--100
R2 : before exiting : 1517579707694
R1 : before exiting : 1517579707694
我正在 Java 中学习多线程,并且正在试验线程。我想出了一种竞争条件代码(有点......请原谅这个菜鸟),其中 2 个线程循环工作(100 次)并竞相更改静态变量。目标是当一个线程第一次完成循环时(在时间片环境中或并行地 运行)打印变量的值并调用 system.exit(int status) 来终止程序!这是为了找出哪个线程赢得了比赛!
预期输出应为:nameOfTheThreadThatWonTheRace + "--" + valueOf'I'IncrementedInTheLoop
代码如下:
public class Nest
{
public static void main(String[] args) throws Exception
{
Thread r1 = new Thread(new Racer(),"R1");
Thread r2 = new Thread(new Racer(),"R2");
r1.start();
r2.start();
}
}
class Racer implements Runnable
{
public void run()
{
for(int i = 0; i <= 100; i++)
{
Value.value = Thread.currentThread().getName() + "--" + i;
}
Value.printValue();
System.exit(0);
}
}
class Value
{
static String value = null;
public static void printValue()
{
System.out.println(value);
}
}
但是实际输出不同(4 次运行):
R2--100 R2--100
R2--84 R2--100
R1--100 R1--100
R2--39 R2--100
我很困惑为什么 JVM 在任一线程到达 'System.exit(0)' 行后不停止? exit() 是否仅关闭主线程或整个 JVM,或者仍在执行的线程正在阻止 JVM 暂停?
另外请解释一下为什么要生成2行o/p?
For extra info:
Processor--> Intel® Core™ i5-7200U CPU @ 2.50GHz × 4
Ram--> 8GB
OS--> Fed27 workstation
(我还没有接触过 java.util.concurrent API 'yet' 但我知道我可以在那里以不同的方式管理线程..)
如果您能用正常的线程术语而不是指并发 API 来解释,我将不胜感激。
感谢您的帮助,再次原谅这个菜鸟:)
处理 System.exit(0)
需要时间,因此当调用它的线程正在等待操作系统终止并回收 运行 在不同内核上运行的代码时,就是运行ning在不同的内核上都能完成。这使它看起来像两个线程 "won the race".
请记住,在多线程环境中,一个线程无法显式控制另一个线程的时间;即使在系统关闭时。如果你想要那种控制,你需要明确地将它写入程序(例如通过让两个线程检查线程安全标志,以确定是否仍在竞争运行)。
调用 System.exit() 将关闭 JVM(请参阅 javadocs or the language specs)。
两个线程正在并行更新 Value 的静态成员。此类不安全更新的结果未定义。这就是您看到 strage 输出的原因。
一种解决方案是在 Racer class 中使用局部变量或字段,因为您不必在两个线程之间共享数据。此外,您甚至不需要它,因为您可以使用 Thread.currentThread().getName()
获取当前线程的名称我想如果你在你的程序中添加一点日志记录,那么它可以帮助你理解到底发生了什么:
public void run()
{
for(int i = 0; i <= 100; i++)
{
if(i==100)
{
System.out.println(Thread.currentThread().getName() +" : before setting value 100th time : " + System.currentTimeMillis());
}
Value.value = Thread.currentThread().getName() + "--" + i;
if(i==100)
{
System.out.println(Thread.currentThread().getName() +" : after setting value 100th time : " + System.currentTimeMillis());
}
}
System.out.println(Thread.currentThread().getName() +" : before printing : " + System.currentTimeMillis());
Value.printValue();
System.out.println(Thread.currentThread().getName() +" : before exiting : " + System.currentTimeMillis());
System.exit(0);
}
class Value
{
static String value = null;
public static void printValue()
{
System.out.println(Thread.currentThread().getName() + " : value : " + value + " : " + System.currentTimeMillis());
}
}
首先,如果任何线程调用 System.exit(),那么 JVM 将终止(杀死所有线程!!!)。它不会等待任何线程执行,但会调用关闭挂钩、未调用的终结器等。因此,JVM 可能需要一些时间才能完成。您可以在这里阅读更多内容:
https://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#exit(int)
现在,您只提到了 4 运行 的输出。如果你再 运行 几次,我相信你会得到以下输出:
R2--100
这显然意味着 JVM 在另一个线程可以执行之前终止。
现在对于你的输出,说
R2--100 R2--100
两个线程都在 JVM 终止之前执行,很简单!
需要注意的一件事是两个线程的名称都是 R2。这是因为值变量是静态的并且在两个线程之间共享。由于竞争条件,在 R2 可以打印该值之前,它已由 R1 设置。如果您添加我建议的日志记录,您可以看到这一点。
参见下面的示例输出:
R2 : before setting value 100th time : 1517579707689
R2 : after setting value 100th time : 1517579707690
R1 : before setting value 100th time : 1517579707689
R1 : after setting value 100th time : 1517579707691
R2 : before printing : 1517579707691
R1 : before printing : 1517579707692
R2 : value : R1--100
R1 : value : R1--100
R2 : before exiting : 1517579707694
R1 : before exiting : 1517579707694