我有这个java代码使用Threads来计算一旦点击开始按钮直到没有按下停止按钮所经过的时间。
我想使用仅限主题
执行此操作import javax.swing.*;
import java.awt.event.*;
// This will count the elapsed time between running time of two threads.
class ThreadGame {
JButton button;
MyAction my_action;
public static void main(String[] args) {
ThreadGame tg = new ThreadGame();
}
public ThreadGame() {
JFrame frame = new JFrame("Calculate time - Game");
button = new JButton("Start");
button.addActionListener(new MyAction());
frame.add(button);
frame.setSize(400, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
class MyAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
String text = (String) e.getActionCommand();
final Timer timer = new Timer();
if (text.equals("Start")) {
button.setText("Stop");
Thread start_time = new Thread() {
public void run() {
timer.startTime();
}
};
start_time.start();
try {
start_time.join();
} catch (Exception e1) {
}
} else {
Thread stop_time = new Thread() {
public void run() {
timer.stopTime();
}
};
Thread get_time = new Thread() {
public void run() {
timer.getElapsedTime();
System.out.println(timer.elapsed);
}
};
stop_time.start();
try {
stop_time.join();
} catch (Exception e2) {
}
get_time.start();
button.setText("Start");
}
}
}
class Timer {
public double startTime = 0.0;
public double stopTime = 0.0;
public boolean running = false;
public double elapsed = 0.0;
public void startTime() {
this.startTime = System.nanoTime();
this.running = true;
}
public void stopTime() {
this.stopTime = System.nanoTime();
this.running = false;
}
// Elasped time in seconds
public double getElapsedTime() {
// double elapsed;
if (running) {
elapsed = ((System.nanoTime() - startTime) / 1000);
} else {
elapsed = ((stopTime - startTime) / 1000);
}
return elapsed;
}
}
}
EDIT:
我理解了这个问题:timer
范围是问题。
EDIT 2:
好的,看起来我只需要在一个帖子中使用suspend
和resume
。
答案 0 :(得分:1)
您的问题是由timer
的范围引起的。这应该是私有实例变量,而不是本地方法变量。此外,在线程的startTime
方法中包含对endTime
和run
的调用并没有获得任何好处,因为这些是非常短暂的调用。但这不是真正的问题。
没有理由在自己的线程中运行Timer
。也就是说,如果不使用专门的实时操作系统,使用线程来解决测量两个事件之间持续时间的问题就是完全错误。
您可能认为可以创建一个带有循环的线程,该循环在msec
之后递增Thread.sleep(1)
变量。 不要这样做!这种时机也只是错误的。您的计算机使用抢占式多任务模型,这意味着您的线程将定期执行无保证。也就是说,没有任何要求Thread.sleep(1)
将在maximum
个持续时间内休眠。保证您的线程将睡眠最小 1ms。这意味着如果您自己在软件中管理时钟,则无法确定时钟错误,并且此错误并非无关紧要。 只是不要这样做!! 时间应始终由您的操作系统来衡量,最好使用基于中断的计时器(这是System.nanoTime
在大多数(如果不是所有平台)上的工作方式)
不要使用线程,只需直接从原始主题调用startTime
和stopTime
方法。
试试这个:
class ThreadGame {
JButton button;
MyAction my_action;
private final Timer timer = new Timer();
public static void main(String[] args) {
ThreadGame tg = new ThreadGame();
}
public ThreadGame() {
JFrame frame = new JFrame("Calculate time - Game");
button = new JButton("Start");
button.addActionListener(new MyAction());
frame.add(button);
frame.setSize(400, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
class MyAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
String text = (String) e.getActionCommand();
if (text.equals("Start")) {
timer.startTime();
button.setText("Stop");
} else {
timer.stopTime();
button.setText("Start");
}
}
}
class Timer {
public double startTime = 0.0;
public double stopTime = 0.0;
public boolean running = false;
public double elapsed = 0.0;
public void startTime() {
this.startTime = System.nanoTime();
this.running = true;
}
public void stopTime() {
this.stopTime = System.nanoTime();
this.running = false;
}
// Elasped time in seconds
public double getElapsedTime() {
return (this.startTime-this.stopTime)*1000000000.0;
}
}
}
如果您想学习如何使用线程,请尝试编写一个解决问题的应用程序,以解决哪些线程非常适合。例如,编写一个允许您下载文件的小型Swing应用程序来自网络。在下载文件时,请更新UI中的进度条。下载应该在与UI线程分开的工作线程中进行,否则UI将在下载过程中阻止。
另一个示例问题是编写一个线程光线跟踪器(这里是用C ++编写的example tutorial)。
如果你想要更简单的东西,可以写一个Swing时钟。在单独的线程中使用循环以定期间隔更新UI,但不使用循环来管理它的时间。同样,不要试图在循环中保持时间,只是让操作系统保留时间,并使用循环来安排UI何时使用当前操作系统时间进行更新。
答案 1 :(得分:1)
问题是按下启动按钮是为了启动不同的 Timer
对象而不是按停止按钮按钮,因为每次都会创建Timer
对象调用actionPerformed(...)
方法。
Timer
必须是MyAction
课程中的字段。您也不需要所有的线程启动/连接,因为Timer
对象非常简单快速。
实际上,您可以使用startTimeMillis
长字段而不是计时器。类似的东西:
class MyAction implements ActionListener {
private long startTimeMillis;
public void actionPerformed(ActionEvent e) {
String text = (String) e.getActionCommand();
if (text.equals("Start")) {
startTimeMillis = System.currentTimeMillis();
...
} else {
System.out.println(System.currentTimeMillis() - startTimeMillis);
}
}
}
答案 2 :(得分:0)
您永远不会致电更新getElapsedTime()
字段的elapsed
。
答案 3 :(得分:0)
只需这样做......
- 在线程开始时致电System.currentTimeMillis()
。
- 然后再次在结束时调用System.currentTimeMillis()
。
- Subtract
结束时的起始值可以获得经过的时间......
<强> ///////////////// EDITED /////////////////////// 强>
确保method
试图操纵(即读取和写入)持有variable
的{{1}}必须与System.currentTimeMillis()
同步,以便竞争条件根据{{1}} ...
synchronized keyword
答案 4 :(得分:0)
单击按钮时,您正在创建新的Timer
。使计时器成为MyAction
以下代码应足以获得经过的时间。
class MyAction implements ActionListener {
final Timer timer = new Timer();
public void actionPerformed(ActionEvent e) {
String text = (String) e.getActionCommand();
if (text.equals("Start")) {
button.setText("Stop");
timer.startTime();
} else {
timer.stopTime();
System.out.println(timer.elapsed);
button.setText("Start");
}
}
}