用Java制作一个简单的计时器

用Java制作一个简单的计时器,java,timer,Java,Timer,我似乎不知道如何用java制作一个简单的计时器。我所需要做的只是显示时间,真的。因此,这只是一个开始方法,它一直在计算,比如0:00、0:01、0:02等等。我在论坛上看到过一些类似的帖子,但所有的代码对于我的理解水平来说都有点复杂;我对java有点陌生。但是要制作一个只执行如此基本功能的计时器应该不会那么难吧?如果有人能帮忙,我们将不胜感激:)这并不难。然而,我要提醒您,我已经看到了一些关于堆栈溢出的非常混乱的答案,在某些情况下,编码习惯非常糟糕,所以要非常小心。首先让我回答这个问题 如果程序

我似乎不知道如何用java制作一个简单的计时器。我所需要做的只是显示时间,真的。因此,这只是一个开始方法,它一直在计算,比如0:00、0:01、0:02等等。我在论坛上看到过一些类似的帖子,但所有的代码对于我的理解水平来说都有点复杂;我对java有点陌生。但是要制作一个只执行如此基本功能的计时器应该不会那么难吧?如果有人能帮忙,我们将不胜感激:)

这并不难。然而,我要提醒您,我已经看到了一些关于堆栈溢出的非常混乱的答案,在某些情况下,编码习惯非常糟糕,所以要非常小心。首先让我回答这个问题

如果程序员在实现计时器时犯的最大错误似乎是认为他们需要一些东西来跟踪当前时间。也就是说,他们编写了某种循环,每秒钟递增一个变量,或者类似的傻事。您不需要编写代码来跟踪时间。函数
System.currentTimeMillis()
将为您实现这一点,而且它非常精确

计时器代码将涉及许多程序员混淆的两个方面:

  • 时间的计算
  • 显示器的刷新
  • 要计算显示时间,只需记录计时器启动的时间:

    long startTime = System.currentTimeMillis();
    
    稍后,当您想要显示时间量时,您只需从当前时间中减去它

    long elapsedTime = System.currentTimeMillis() - startTime;
    long elapsedSeconds = elapsedTime / 1000;
    long secondsDisplay = elapsedSeconds % 60;
    long elapsedMinutes = elapsedSeconds / 60;
    //put here code to format and display the values
    
    程序员犯的最大错误是认为他们需要一个变量来保存当前时间,然后编写代码以每秒递增该变量,例如,他们维护的称为“elapsedSeconds”的东西。问题在于,您可以安排每秒调用一次代码,但无法保证该代码将在何时被调用。如果系统正忙,那么调用该代码的时间可能会比调用第二个代码晚很多。如果系统非常繁忙(例如,从故障磁盘获取页面),那么实际上可能会延迟几秒钟。使用Thread.sleep(1000)函数每秒循环一次的代码会发现错误会随着时间的推移而累积。如果睡眠时间有一次延迟300毫秒,那么这个错误会在你计算时间的时候出现。这是完全没有必要的,因为操作系统有一个功能告诉你当前时间

    long elapsedTime = System.currentTimeMillis() - startTime;
    long elapsedSeconds = elapsedTime / 1000;
    long secondsDisplay = elapsedSeconds % 60;
    long elapsedMinutes = elapsedSeconds / 60;
    //put here code to format and display the values
    
    无论您是每秒运行此代码一次、每秒运行100次,还是每3.572秒运行一次,上述计算都是准确的。关键是无论何时调用此代码,
    currentTimeMillis()
    都是时间的精确表示,这是一个重要的考虑因素,因为线程和计时器事件不能保证在特定时间准确

    计时器的第二个方面是刷新显示。这将取决于您使用的显示技术。在GUI环境中,您需要计划绘制事件。您希望这些绘制事件在预期显示更改的时间之后立即发生。然而,这很棘手。您可以请求绘制事件,但可能有数百个其他绘制事件排队等待处理

    一种懒惰的方法是每秒安排10个绘制事件。由于时间的计算不依赖于在特定时间点调用的代码,并且如果使用相同的时间重新绘制屏幕也无关紧要,因此这种方法或多或少保证显示的时间将在大约1/10秒内显示正确的时间。这似乎有点浪费,因为10次中有9次你在画屏幕上已经出现的东西

    如果您正在编写一个带有某种动画(如游戏)的程序,该程序每秒刷新屏幕30次,则无需执行任何操作。只需将计时器显示调用合并到常规屏幕刷新中即可

    如果绘制事件很昂贵,或者如果您正在编写一个执行终端样式输出的程序,则可以通过计算显示更改之前的剩余时间量来优化事件调度:

    long elapsedTime = System.currentTimeMillis() - startTime;
    long timeTillNextDisplayChange = 1000 - (elapsedTime % 1000);
    
    变量TIMETILNEXTDISPLAYCHANGE保存您需要等待的毫秒数,直到计时器的秒数部分发生变化。然后,您可以计划在该时间发生绘制事件,可能会调用
    Thread.sleep(timeTillNextDisplayChange)
    ,然后在睡眠后执行输出。如果代码在浏览器中运行,则可以使用此技术在正确的时间更新页面DOM

    请注意,此显示刷新计算中没有影响计时器本身精度的内容。线程可能会延迟10毫秒甚至500毫秒从睡眠状态返回,并且计时器的准确性不会受到影响。每次通过时,我们都从currentTimeMillis计算等待时间,因此在某个场合被称为late不会导致以后的显示延迟


    这是一个精确计时器的关键。不要期望操作系统在您要求时调用您的例程或发送绘制事件。当然,在现代机器上,操作系统通常具有显著的响应速度和准确性。这种情况发生在测试环境中,在测试环境中,您没有运行太多其他程序,并且计时器似乎工作正常。但是,在生产中,在很少出现压力的情况下,您不希望计时器“漂移”,因为系统很忙。

    您可以使用
    java.util
    中的
    timer
    类,也可以使用另一种更复杂的方法,即线程。计时器也有线程动作,但使用它很容易理解。

    要创建一个简单的计时器,正如您根据需要解释的那样,很容易为此编写代码。我已经写了下面的代码供您参考。如果你希望你可以提高它

    导入java.util.concurrent.TimeUnit; 公共类计时器{

    public static void main(String[] args) throws InterruptedException 
    {
        boolean x=true;
        long displayMinutes=0;
        long starttime=System.currentTimeMillis();
        System.out.println("Timer:");
        while(x)
        {
            TimeUnit.SECONDS.sleep(1);
            long timepassed=System.currentTimeMillis()-starttime;
            long secondspassed=timepassed/1000;
            if(secondspassed==60)
            {
                secondspassed=0;
                starttime=System.currentTimeMillis();
            }
            if((secondspassed%60)==0)
            displayMinutes++;
    
        System.out.println(displayMinutes+"::"+secondspassed);
        }
    
    }
    

    }

    带有显示器的计时器将涉及线程。如果您是Java新手,请