用Java制作一个简单的计时器 [英] Make a simple timer in Java

查看:31
本文介绍了用Java制作一个简单的计时器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我似乎无法弄清楚如何在 Java 中制作一个简单的计时器.我需要它做的只是显示时间,真的.所以只是一个开始方法,它会像 0:00、0:01、0:02 等一样不断计数.我看过其他一些类似的论坛帖子,但所有代码对于我的水平来说都有些复杂理解;我对java有点陌生.但是制作一个只执行这种基本功能的定时器应该不难吧?如果有人可以提供帮助,将不胜感激:)

I can't seem to figure out how to make a simple timer in java. All I need it to do is just display time, really. So just a start method, and it keeps counting up like 0:00, 0:01, 0:02, etc. I've seen some other similar forum posts on this, but all the code is kind of complicated for my level of understanding; I'm kind of new to java. But it shouldnt be that hard to make a timer that just performs such a basic function? If anyone could help it would be greatly appreciated :)

推荐答案

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

This is not difficult. However, I would caution you that I have seen some very confused answers on stack overflow, in some cases shockingly poor coding habits, so be very careful. First let me answer the question.

如果程序员在实现计时器时犯的最大错误似乎是认为他们需要一些东西来跟踪当前时间.也就是说,他们编写了某种循环,每秒增加一个变量或一些愚蠢的事情.您无需编写代码来跟踪时间.函数 System.currentTimeMillis() 会为你做到这一点,而且它做得非常准确.

If seem that the biggest mistake that programmers make in implementing a timer, is thinking that they need something to keep track of the current time. That is, they write some sort of loop that increments a variable every second or some such silly thing. You do not need to write code to keep track of the time. The function System.currentTimeMillis() will do that for you, and it does it quite accurately.

定时器代码会涉及到很多程序员混淆的两个方面:

Timer code will involve two aspects which many programmers mix up:

  1. 计算时间
  2. 刷新显示

计算显示时间所需要做的就是记录计时器开始的时间:

All you need to do to calculate the time to display, is to record the time that the timer started:

long startTime = System.currentTimeMillis();

稍后,当您想要显示时间量时,只需从当前时间中减去即可.

Later, when you want to display the amount of time, you just subtract this from the current time.

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) 函数每秒循环的代码会发现错误随着时间的推移而累积.如果 sleep 一次返回 300 毫秒,则该错误会复杂到您对时间的计算中.这完全没有必要,因为操作系统有一个告诉你当前时间的功能.

The biggest mistake that programmers make is to think they need a variable to hold the current time and then to write code to increment that variable every second, e.g. something called "elapsedSeconds" which they maintain. The problem is that you can schedule code to be called every second, but there is no guarantee of exactly when that code will be called. If the system is busy, that code might be called quite a bit later than the second. If the system is extremely busy (for example page fetching from a faulty disk) it could actually be several seconds late. Code that uses the Thread.sleep(1000) function to loop every second will find that the error builds up over time. If sleep returns 300ms late one time, that error is compounded into your calculation of what time it is. This is all completely unnecessary because the OS has a function to tell you the current time.

无论您是每秒运行此代码、每秒运行 100 次还是每 3.572 秒一次,上述计算都将是准确的.关键是 currentTimeMillis() 是时间的准确表示,无论何时调用此代码——这是一个重要的考虑因素,因为不能保证线程和计时器事件在特定的时间是准确的时间.

The above calculation will be accurate whether you run this code every second, 100 times a second, or once every 3.572 seconds. The point is that currentTimeMillis() is the accurate representation of the time regardless of when this code is called -- and that is an important consideration because thread and timer events are not guaranteed to be accurate at a specific time.

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

The second aspect of a timer is refresh of the display. This will depend upon the technology you are using to display with. In a GUI environment you need to schedule paint events. You would like these paint events to come right after the time that the display is expected to change. However, it is tricky. You can request a paint event, but there may be hundreds of other paint events queued up to be handled before yours.

一种懒惰的方法是每秒安排 10 个绘制事件.因为时间的计算不依赖于在特定时间点被调用的代码,而且因为如果你用同一时间重新绘制屏幕也没有关系,这种方法或多或少保证了显示的时间在大约 1/10 秒内显示正确的时间.这似乎有点浪费,因为 10 次中有 9 次您正在绘制屏幕上已有的内容.

One lazy way to do this is to schedule 10 paint events per second. Because the calculation of the time does not depend on the code being called at a particular point in time, and because it does not matter if you re-paint the screen with the same time, this approach more or less guarantees that the displayed time will show the right time within about 1/10 of a second. This seems a bit of a waste, because 9 times out of 10 you are painting what is already on the screen.

如果您正在编写一个带有某种动画(如游戏)的程序,该程序每秒刷新屏幕 30 次,那么您什么都不用做.只需将计时器显示调用合并到您的常规屏幕刷新中即可.

If you are writing a program with animation of some sort (like a game) which is refreshing the screen 30 times a second, then you need do nothing. Just incorporate the timer display call into your regular screen refresh.

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

If paint events are expensive, or if you are writing a program that does terminal-style output, you can optimize the scheduling of events by calculating the amount of time remaining until the display will change:

long elapsedTime = System.currentTimeMillis() - startTime;
long timeTillNextDisplayChange = 1000 - (elapsedTime % 1000);

变量 timeTillNextDisplayChange 保存您需要等待的毫秒数,直到计时器的秒数部分发生变化.然后您可以安排一个绘制事件在那个时间发生,可能调用 Thread.sleep(timeTillNextDisplayChange) 并在睡眠后进行输出.如果您的代码在浏览器中运行,您可以使用此技术在适当的时间更新页面 DOM.

The variable timeTillNextDisplayChange holds the number of milliseconds you need to wait until the seconds part of the timer will change. You can then schedule a paint event to occur at that time, possibly calling Thread.sleep(timeTillNextDisplayChange) and after the sleep do the output. If your code is running in a browser, you can use this technique to update the page DOM at the right time.

请注意,此显示刷新计算中没有任何内容会影响计时器本身的准确性.线程可能会延迟 10 毫秒,甚至延迟 500 毫秒从睡眠中返回,并且不会影响计时器的准确性.每次通过时,我们都会根据 currentTimeMillis 计算等待时间,因此一次调用延迟不会导致后面的显示延迟.

Note, that there is nothing in this calculation of the display refresh that effects the accuracy of the timer itself. The thread might return from sleep 10ms late, or even 500ms late, and the accuracy of the timer will not be effected. On every pass we calculate the time to wait from the currentTimeMillis, so being called late on one occasion will not cause later displays to be late.

这是准确计时器的关键.不要期望操作系统在您要求时调用您的例程或发送绘制事件.通常,当然,对于现代机器,操作系统的响应速度非常快且准确.这发生在您没有运行太多其他测试并且计时器似乎工作的测试情况下.但是,在生产中,在罕见的压力情况下,您不希望您的计时器因为系统繁忙而漂移".

That is the key to an accurate timer. Do not expect the OS to call your routine or send the paint event exactly when you ask it to. Usually, of course, with modern machines, the OS is remarkably responsive and accurate. This happens in test situations where you are not running much else, and the timer seems to work. But, in production, under rare stress situation, you do not want your timer "drifting" because the system is busy.

这篇关于用Java制作一个简单的计时器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆