2012-05-30 6 views
3

Я не могу понять, как сделать простой таймер в java. Все, что мне нужно, это просто показать время, действительно. Так что просто метод запуска, и он продолжает подсчитывать, как 0:00, 0:01, 0:02 и т. Д. Я видел некоторые другие подобные сообщения на форуме, но весь код довольно сложный для моего уровня понимание; Я немного новичок в java. Но не должно быть так сложно сделать таймер, который просто выполняет такую ​​базовую функцию? Если бы кто-то мог помочь, было бы весьма полезно :)Сделать простой таймер в Java

+1

Таймер с дисплеем включает в себя резьбу. Если вы новичок в Java и, возможно, программируете в целом, я рекомендую сначала изучить более простые вещи, прежде чем погружаться в потоки. – kevin628

+0

Такой таймер не обязательно включает в себя потоки. Если у вас уже есть цикл событий, этот же существующий цикл можно использовать. Если программа представляет собой программу стиля телетайпа командной строки, то основной (основной) поток может работать достаточно. И если у вас есть программа GUI, вам нужно только убедиться, что экран обновляется чаще, чем пользователь просматривает, и это может быть сделано с использованием возможности таймера GUI. Вы не должны предполагать, что необходима нить. – AgilePro

ответ

17

Это не сложно. Тем не менее, я бы предупредил вас, что я видел некоторые очень запутанные ответы на переполнение стека, в некоторых случаях ужасно плохие привычки кодирования, поэтому будьте очень осторожны. Сначала позвольте мне ответить на вопрос.

Если кажется, что самая большая ошибка, которую программисты делают при реализации таймера, думает, что им нужно что-то, чтобы отслеживать текущее время. То есть они пишут какой-то цикл, который увеличивает каждую секунду переменную или какую-то такую ​​глупую вещь. Вам не нужно писать код, чтобы отслеживать время. Функция System.currentTimeMillis() сделает это за вас, и она делает это довольно точно.

код таймера будет включать в себя два аспекта, которые многие программисты перепутать:

  1. расчет времени
  2. обновления дисплея

Все, что вам нужно сделать, чтобы рассчитать время, чтобы отобразить , необходимо записать время начала таймера:

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 

Самая большая ошибка, что программисты делают это, чтобы думать, что они нуждаются в переменную для хранения текущего времени, а затем написать код, чтобы увеличить эту переменную каждый второй, например, что-то называемое «прошедшими секундами», которое они поддерживают. Проблема в том, что вы можете планировать код, который будет вызываться каждую секунду, но нет гарантии, что именно этот код будет вызван. Если система занята, этот код можно назвать довольно немного позже второго. Если система очень занята (например, выборка страницы с неисправного диска), это может быть на несколько секунд позже. Код, который использует функцию Thread.sleep (1000) для циклирования каждую секунду, обнаружит, что ошибка нарастает с течением времени. Если сон возвращается на 300 мс за один раз, эта ошибка усугубляется в ваш расчет того, в какое время это происходит. Это совершенно не нужно, потому что у ОС есть функция, чтобы сообщить вам текущее время.

Приведенный выше расчет будет точным независимо от того, выполняете ли вы этот код каждую секунду, 100 раз в секунду или один раз каждые 3,572 секунды. Дело в том, что currentTimeMillis() - точное представление времени независимо от того, когда этот код вызывается - и это важно, потому что события потока и таймера не гарантируются точно в определенное время.

Второй аспект таймера - это обновление дисплея. Это будет зависеть от технологии, которую вы используете для отображения. В среде графического интерфейса вам нужно запланировать события рисования. Вы хотели бы, чтобы эти события рисования появились сразу после того, как ожидается, что дисплей изменится. Однако это сложно. Вы можете запросить событие рисования, но могут быть сотни других событий рисования, стоящих перед очередью, которые будут обработаны до вашего.

Один ленивый способ сделать это - запланировать 10 событий краски в секунду.Поскольку вычисление времени не зависит от кода, вызываемого в определенный момент времени, и потому что не имеет значения, если вы повторно нарисовали экран в одно и то же время, этот подход более или менее гарантирует, что отображаемое время будет покажите время в пределах 1/10 секунды. Это кажется пустым, потому что в 9 раз из 10 вы рисуете то, что уже на экране.

Если вы пишете программу с какой-то анимацией (например, игрой), которая освежает экран 30 раз в секунду, вам ничего не нужно. Просто включите вызов дисплея таймера в обычное обновление экрана.

Если краска событие является дорогостоящим, или, если вы пишете программу, которая делает вывод терминала стиля, вы можете оптимизировать планирование событий путем подсчета количества времени, оставшееся до появления на дисплее изменится:

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

Переменная timeTillNextDisplayChange содержит количество миллисекунд, которое нужно ждать, пока секундная часть таймера не изменится. Затем вы можете запланировать событие рисования в это время, возможно, вызывая Thread.sleep(timeTillNextDisplayChange) и после сна вывести результат. Если ваш код работает в браузере, вы можете использовать этот метод для обновления страницы DOM в нужное время.

Обратите внимание, что в этом расчете обновления дисплея ничего нет, что влияет на точность самого таймера. Поток может вернуться из сна 10 мс поздно или даже 500 мс поздно, и точность таймера не будет выполнена. На каждом проходе мы вычисляем время ожидания от currentTimeMillis, поэтому, будучи вызванным с опозданием, не будет приводить к тому, что поздние дисплеи будут опоздать.

Это ключ к точному таймеру. Не ожидайте, что ОС вызовет вашу рутину или отправит событие paint именно тогда, когда вы его попросите. Обычно, конечно, с современными машинами ОС замечательно отзывчива и точна. Это происходит в тестовых ситуациях, когда вы больше не работаете, и таймер работает. Но в производстве, в ситуации редких стрессов, вы не хотите, чтобы ваш таймер «дрейфовал», потому что система занята.

Смежные вопросы