在java中使用线程计算所用的总时间
我有一个java代码,它使用线程来计算从按下开始按钮到不按下停止按钮所经过的时间 我只想使用线程执行此操作在java中使用线程计算所用的总时间,java,multithreading,swing,Java,Multithreading,Swing,我有一个java代码,它使用线程来计算从按下开始按钮到不按下停止按钮所经过的时间 我只想使用线程执行此操作 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
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:
我已经理解了这个问题:定时器
范围就是问题所在
EDIT 2:
好的,看起来我只能在一个线程中使用suspend
和resume
。您从未调用getElapsedTime(),不是局部方法变量。此外,在线程的run
方法中包装对startTime
和endTime
的调用并不会带来任何好处,因为这些调用的寿命非常短。但这不是真正的问题
没有理由在自己的线程中运行Timer
。也就是说,如果不使用专门的实时操作系统,使用线程来解决测量两个事件之间持续时间的问题是完全错误的。
您可能认为可以创建一个线程,该线程的循环在thread.sleep(1)
之后增加msec
变量不要这样做这种时机也是完全错误的。您的计算机使用抢占式多任务模式,这意味着无法保证您的线程将以固定间隔执行。也就是说,没有任何东西需要线程。睡眠(1)
将睡眠一段最长时间。保证您的线程将至少睡眠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应用程序,让您从web下载文件。下载文件时,更新UI中的进度条。下载应该在与UI线程分开的工作线程中进行,否则UI将在下载过程中阻塞
另一个示例问题是编写线程光线跟踪器(这里是用C++编写的)
如果你想要更简单的东西,写一个摆动时钟。在单独的线程中使用循环以定期更新UI,但不要使用循环来管理时间。同样,不要试图在循环中保留时间,只需让操作系统保留时间,并使用循环来安排UI何时使用当前操作系统时间进行更新。只需这样做
-在线程的开始处调用System.currentTimeMillis()
。
-然后在线程的末尾再次调用System.currentTimeMillis()
。
-减去
以起始值结束以获得经过的时间
///EDITED/////strong>
确保试图操纵(即读写)持有系统的变量的方法必须与同步关键字同步。currentTimeMillis()
如果您正在编写一个可能会被另一个线程读取的变量,或者正在读取一个可能上次被另一个线程写入的变量,则必须使用同步,然后,读写器必须使用相同的监视器锁进行同步。
问题在于,按下“开始”按钮会启动与按下“停止”按钮不同的计时器对象,因为每次执行操作时都会创建计时器对象(…)
方法被调用
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);
}
}
}
单击按钮时,您正在创建一个新的计时器。使计时器成为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");
}
}
}
除了旋转许多毫无意义的线程之外,完全不清楚您想要完成什么。如果您只想记录两次按键之间的时间,请将开始和结束时间保存在某个位置,并在ActionListener
中更新它们。如果您试图创建一个不断更新的计数器,请查看javax.swing.Timer
。如果您只是尝试学习线程,那么您应该在按下start时分叉一个线程,该线程会计算某种值。然后当按下停止键时,您可以调用thread.interrupt()
来停止线程。@格雷:是的,我将使用thread.interrupt()
或suspend()
和resume()
方法。thread.suspend()
和resume()
方法已弃用,不应使用。@Gray-这是一种非常糟糕的计时方法。有关说明,请参见下面的“我的编辑”。如果你想学习一个新的编程概念,你应该