Java 在system.exit()之后仍在运行的线程

Java 在system.exit()之后仍在运行的线程,java,multithreading,jvm,java-threads,system.exit,Java,Multithreading,Jvm,Java Threads,System.exit,我正在学习Java中的多线程技术,并尝试使用线程。我想出了一种赛车状态代码,有点。。。请原谅这个noob,其中两个线程在一个循环中工作100次,并竞相更改一个静态变量。目标是当线程第一次完成在时间切片环境中运行或并行运行的循环时,打印变量的值并调用system.exitint status以终止程序!这只是为了找出哪个线程赢得了比赛 预期的输出应该是:name of thread,它将在循环中递增'I'的ACE+-+值 代码如下: public class Nest { public sta

我正在学习Java中的多线程技术,并尝试使用线程。我想出了一种赛车状态代码,有点。。。请原谅这个noob,其中两个线程在一个循环中工作100次,并竞相更改一个静态变量。目标是当线程第一次完成在时间切片环境中运行或并行运行的循环时,打印变量的值并调用system.exitint status以终止程序!这只是为了找出哪个线程赢得了比赛

预期的输出应该是:name of thread,它将在循环中递增'I'的ACE+-+值

代码如下:

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);
  }
}
我还没有接触到java.util.concurrent API,但我知道我可以在那里以不同的方式管理线程

如果您能用普通的线程术语而不是并发API进行解释,我将不胜感激

再次感谢您的帮助并原谅此noob:

处理System.exit0需要时间,因此当调用它的线程等待操作系统终止并回收在不同内核上运行的代码时,在不同内核上运行的代码可以完成。这使它看起来像两个线程赢得了比赛


请记住,在多线程环境中,一个线程无法明确控制另一个线程的计时;甚至在系统关闭时也没有。如果需要这种控制,需要将其显式写入程序,例如让两个线程检查线程安全标志,以确定竞赛是否仍在运行。

调用System.exit将关闭JVM。请参阅或

值的静态成员由两个线程并行更新。未定义此类不安全更新的结果。这就是您看到strage输出的原因


解决方案是在Racer类中使用局部变量或字段,因为您不必在两个线程之间共享数据。此外,您甚至不需要它,因为您可以通过

获得当前线程的名称。我认为,如果您在程序中添加一点日志记录,那么它可以帮助您了解真正发生的事情:

    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不工作…你能再解释一下并提到你预期的确切输出吗?实际输出有什么问题?根据您的程序,它们似乎是正确的。System.exit工作正常。是你的代码被破坏了,你的期望是错误的,所以对它的输出感到惊讶是没有什么用处的。我期望的o/p是首先完成循环的线程应该打印出“值”,并且程序应该在该点终止,而不管其他线程如何。。。如果我的程序是错误的…你能帮我纠正它,以获得预期的结果或任何其他指针将是有帮助的谢谢你。。。我想我理解你所说的…所以即使代码是一个核心被杀死了…其他代码中的剩余线程,因为它们仍然在运行,可以阻止JVM停止…正确吗?@shashikanthchillappagari其他线程不会阻止JVM停止,它们只是在一个线程调用System.exit0之后和操作系统强制终止未调用System.exit0的线程之前结束。System.exit0也需要时间才能运行!当然,您的程序还存在其他问题,但是假设JVM在调用System.exit0的那一刻就从所有内核中完全移除,这并不是事情的工作方式。线程调用System.exit0向操作系统发出请求,操作系统随后处理该请求,这需要时间。这消除了我的疑问…谢谢。。。我又运行了几次,得到了单输出结果。。。谢谢分享
    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());
  }
}
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