我要求做一个穿线练习-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
答案 0 :(得分:1)
不幸的是,我无法重现您所描述的行为。但是,我的猜测是使用signal and await或notify 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”块已经存在一段时间了,这是文档中描述的正常行为: