【问题标题】:How to make a stopwatch as a thread in Java?如何将秒表制作为Java中的线程?
【发布时间】:2013-11-21 06:47:43
【问题描述】:


我正在尝试实现一个类似于Is there a stopwatch in Java? 的秒表,但作为Thread

我的SecondsCounter 类实现了Runnable,然后调用它的start 方法将创建一个线程作为局部变量。

似乎该线程与run 方法中的第一行冲突:this.runningTime = System.currentTimeMillis(); ...因为条件while (this.runningTime < this.endTime) 从不 损坏(无限循环)...

那么让一个类既实现Runnable 并且包含它的Thread 也是不正确的吗?



这是具有主要方法的类:
public class MultithreadingTest {

    public static void main(String[] args) {
        int totalSeconds = 5;
        SecondsPrinter printer = new SecondsPrinter(totalSeconds);
        printer.startPrinting();
    }
} // end of class


...秒打印机类:

public class SecondsPrinter {

    // composition here:
    private SecondsCounter clock;

    public SecondsPrinter(int totalSeconds) {
        this.clock = new SecondsCounter(totalSeconds);
    }

    public void startPrinting() {
        this.clock.start();
        while (this.clock.isRunning()) {

            // this is incorrectly always printing the maximum seconds value:
            System.out.println(this.clock.getCurrentSecond());
        }
    }
} // end of class


...和秒计数器类:

public class SecondsCounter implements Runnable {

    private int totalSeconds, currentSecond;
    private long startTime, runningTime, endTime;
    private Thread thread;

    public SecondsCounter(int totalSeconds) {
        this.totalSeconds = totalSeconds;
    }

    public int getCurrentSecond() {
        return this.currentSecond;
    }

    @Override
    public void run() {
        this.runningTime = System.currentTimeMillis();

        // this is an infinite loop, but it shouldn't be:
        while (this.runningTime < this.endTime) {
            this.currentSecond = (int)(this.endTime - this.runningTime) / 1000;
        }

        // this code is never reached:
        this.stop();
    }

    public void start() {
        this.startTime = System.currentTimeMillis();
        this.runningTime = this.startTime;
        this.endTime = this.startTime + (this.totalSeconds * 1000);

        // multithreading here:
        this.thread = new Thread(this);
        this.thread.start();
    }

    public boolean isRunning() {
        return this.thread.isAlive();
    }

    public void stop() {
        this.thread.interrupt();
        this.thread = null;
    }
} // end of class

【问题讨论】:

  • 那是很多代码。我会考虑如何简化它来做你想做的事情。
  • @PeterLawrey -- 嗯,我可以消除SecondsCounter 类中的startTime 变量,并可能将毫秒而不是秒传递给它的构造函数以简化一些单位转换的东西。我可以改用java.util.Timer,但我这样做只是为了试验线程。否则,我不会注意到任何 关注点分离 问题或违反 DRY.. 您有什么建议?

标签: java multithreading time


【解决方案1】:

其实这应该是一个无限循环。看看你的循环。

while (this.runningTime < this.endTime) {
    this.currentSecond = (int)(this.endTime - this.runningTime) / 1000;
}

条件表明它将在runningTime &lt; endTime 时循环。 runningTime 在哪里更新?如果你在循环中添加这样的东西,它应该可以工作:

public void run() {
    this.runningTime = System.currentTimeMillis();

    // no longer an infinite loop
    while (this.runningTime < this.endTime) {
        this.currentSecond = (int)(this.endTime - this.runningTime) / 1000;
        this.runningTime = System.currentTimeMillis();
    }

    // this code is now reached.
    this.stop();
}

您甚至可以组合它(或完全删除变量 runningTime):

public void run() {
    while ((this.runningTime = System.currentTimeMillis()) < this.endTime) {
        this.currentSecond = (int)(this.endTime - this.runningTime) / 1000;
    }

    this.stop();
}

【讨论】:

  • 哦,我完全错过了,哦!现在它可以正常工作了,感谢@Quincunx 的帮助。
  • 有趣,我不知道你可以设置然后使用一个值作为while循环的条件,谢谢@Quincunx!当设置在括号中时,此 only 似乎有效,如下所示:while( ( this.runningTime = System.currentTimeMillis() ) &lt; this.endTime) { ...由于&lt; 的运算符优先级问题,它似乎在没有括号的情况下无法编译。
  • @IanCampbell 这很有效,因为赋值运算符也返回它分配的值。它只适用于括号,因为赋值运算符具有最低的operation precendence,所以没有括号,我们得到this.runningTime = (System.currentTimeMillis() &lt; this.endTime);。括号很好。
猜你喜欢
  • 1970-01-01
  • 2021-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-03
  • 2012-06-11
  • 1970-01-01
相关资源
最近更新 更多