Java-空while循环+多线程卡住了我的程序

时间:2018-12-01 21:14:05

标签: java multithreading performance compilation runtime

我要求做一个穿线练习-3个将在比赛中成为“跑步者”的线程,然后单击Enter将完成其中一个线程的运行,并返回花费他运行的时间。

因此我做了这段代码-

赛跑者类别:

import java.util.*;
public class Runner extends Thread {
    Date startDate;
    long startTime;    
    String name;
    private volatile boolean flag = true;

    //This method will set flag as false
    Runner(String name)
    {
        this.name = name;
    }
    public void stopRunning()
    {
        flag = false;
    }

    @Override
    public void run()
    {
        this.startDate = new Date();
        this.startTime = this.startDate.getTime();
        System.out.println(startTime);         
        while (flag)
        {
        }
        Date d = new Date();
        System.out.println(this.name + " Stopped Running....");
        System.out.println("The time that passed is " + Long.toString((d.getTime()-this.startTime)/1000) + " secondes" );
    }
}

主要:

import java.io.*;
public class Main {
    public static void main(String args[])
    {
        Runner run1 = new Runner("run1");
        Runner run2 = new Runner("run2");
        Runner run3 = new Runner("run3");
        run1.start();
        run2.start();
        run3.start();
        try {
            System.in.read();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            System.in.read();
        } catch (IOException e) {
            e.printStackTrace();
        }
        run1.stopRunning();
        try {
            System.in.read();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            System.in.read();
        } catch (IOException e) {
            e.printStackTrace();
        }

        run2.stopRunning();
        try {
            System.in.read();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            System.in.read();
        } catch (IOException e) {
            e.printStackTrace();
        }
        run3.stopRunning();
    }
}

代码仅创建了Runner的3个线程,而不是他等待ENTER输入(在我的代码测试中,我不得不为每个ENTER输入2次而不是1次输入)功能已启用,线程停止运行。

我的问题是,当我运行它(在eclipse上)时,它花费了Java约5秒钟的时间对所有三个线程执行thread.run(),但是在我测试它的时候我发现如果我添加while(flag) )在Runner类上循环,像System.out.println(this.name)这样的简单输出正常运行,并且java / eclipse编译并运行其

有人知道向我解释发生了什么事,或者我如何在不添加此行的情况下将其解决?

非常感谢

Omer

2 个答案:

答案 0 :(得分:1)

不幸的是,我无法重现您所描述的行为。但是,我的猜测是使用signal and awaitnotify and wait将解决此问题。由于通知和等待的使用要简单得多,因此我选择像这样修复它:

import java.util.*;

public class Runner extends Thread {
    Date startDate;
    long startTime;    
    String name;
    private boolean flag = true;

    //This method will set flag as false
    Runner(String name)
    {
        this.name = name;
    }

    public synchronized void stopRunning()
    {
        flag = false;
        notifyAll(); //Think about if you really need the All
    }

    @Override
    public synchronized void run()
    {
        this.startDate = new Date();
        this.startTime = this.startDate.getTime();
        System.out.println(startTime);         
        while (flag) {
            try { //Just for the sake of compiling - you may think of a better solution
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace(); 
            }
        }
        Date d = new Date();
        System.out.println(this.name + " Stopped Running....");
        System.out.println("The time that passed is " + Long.toString((d.getTime()-this.startTime)/1000) + " secondes" );
    }
}

为方便地解释系统上可能发生的情况,假设您的计算机仅运行一个线程。现在,一旦输入RunnerX.run,由于没有其他线程可以更改bool标志,因此有效的执行将陷入while循环中。
为防止这种情况,您想“告诉ThreadRunner”来更改线程。 (因为您的程序将只等待bool标志更改,所以不再需要执行当前线程。)您可以通过调用wait来做到这一点(这不是很直观吗?)。
现在,您只需要保证通知仍在等待的线程可以再次工作即可。您可以通过致电notify来实现。

我刚刚描述的内容并非100%准确,但应该让您对发生的问题有直观的认识。锁和条件实际上是最基本的,如果您想继续进行并发编程,则应该扩展关于此主题的知识。

答案 1 :(得分:0)

没有while(flag)循环,您的三个线程几乎立即完成,因为它们没有理由在执行Run方法中的几次调用之后等待。
在输入第一个try块之前,这种情况可能已经发生。

我没有测试您的代码,但是也许“ System.in.read”块已经存在一段时间了,这是文档中描述的正常行为:

http://repo.msys2.org/mingw/x86_64/