1. Метод Thread.sleep()

В работу программы на Java можно вставлять паузы. Обычно это не нужно, т.к. пользователи хотят, чтобы их программы работали как можно быстрее. И вряд ли кто-то из них обрадуется, если вы будете специально замедлять свой код.

Но у вас как у программиста может быть куча ситуаций, когда пауза в коде может быть полезной. Например, вы программируете игру и хотите, чтобы она делала какие-то действия раз в две секунды или несколько раз в секунду.

В общем, пауза вещь полезная, поэтому смотрим, как же добавить паузу в код. Это на самом деле очень просто:

Thread.sleep(время);

Где время — это длина паузы в миллисекундах (1/1000 часть секунды).

Исполнение такой команды приостановит вашу программу на время миллисекунд. Примеры:

Thread.sleep(2000);
Приостановит программу на 2 секунды.
Thread.sleep(500);
Приостановит программу на полсекунды.
Thread.sleep(60 * 60 * 1000);
Приостановит программу на 1 час.

Вот как это можно использовать на практике. Допустим, мы пишем программу, которая бы запускала космический корабль. Так бы мог выглядеть ее код:

for (int i = 10; i > 0; i--)
{
   System.out.println(i);
   Thread.sleep(1000);
}

System.out.println("Поехали");
Программа будет выводить на экран каждую секунду числа 10, затем 9, затем 8 и т.д.




Когда счет дойдет до 0, программа выведет надпись Поехали.

2. Правильный расчет пауз

Длину паузы считать легко. Если вам нужно, чтобы программа что-то делала раз в секунду, поставьте паузу — 1000 мс. Если 2 раза в секунду, поставьте паузу 500 мс (1000/2).

Если нужно выполнять что-то 15 раз в секунду, паузу делаем длинной 66 мс (1000/15). Вроде бы все очень просто:

Длительность одного витка цикла = 1000 / количество раз в секунду

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

Смотрите. Допустим, у вас есть какое-то действие, выполнение которого занимает 100 мс. Вы хотите, чтобы оно выполнялось 5 раз в секунду. Какую длину паузы вам нужно выбрать? Точно не 200 мс.

Чтобы действие выполнялось 5 раз в секунду, нужно чтобы время выполнения действия + пауза равнялись 200 мс. Тогда оно действительно будет выполняться 5 раз в секунду. В нашем случае действие выполняется 100 мс, значит на паузу остается еще 100 мс

длина паузы = длительность одного витка цикла — время выполнения действия

То, что время выполнения действия гораздо выше нуля, хорошо понимают разработчики игр. Хотя и люди, играющие в игры, тоже.

Если у игры 20 FPS, это значит, что за одну секунду она успевает отрисовать на экране всего 20 кадров. 1000/20 — получаем 50 мс. Именно столько длится время отрисовки кадра игры.



3. Наносекунды

Современные компьютеры гораздо быстрее, чем во времена создания Java. Поэтому паузы в 1 миллисекунду может быть уже недостаточно.

Допустим мы осуществляем какое-то очень быстрое действие и хотим выполнять его 2000 раз в секунду. Как нам сделать паузу в пол миллисекунды?

А вот для этого есть еще одна модификация метода Thread.sleep():

Thread.sleep(миллисекунды, наносекунды);

Данный метод усыпляет программу на указанное время миллисекунд и наносекунд.

Наносекунды — это 1 миллионная от миллисекунд. Поэтому пауза в полторы миллисекунды будет выглядеть так:

Thread.sleep(1, 500_000);

Ну а если вы хотите паузу в 1/10 миллисекунды, вам нужно будет написать так:

Thread.sleep(0, 100_000);

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



4. Класс TimeUnit

Кстати, в Java есть еще один класс, который облегчит вашу жизнь, если вы таки решите сделать ваше приложение еще медленнее — это класс TimeUnit из пакета java.util.concurrent.

И, как вы помните, если пакет класса не java.lang, нужно или добавить строку import java.util.concurrent.TimeUnit;, или писать каждый раз в коде java.util.concurrent.TimeUnit

Этот класс делает то же самое, что и Thread.sleep(), просто удобнее:

TimeUnit.HOURS.sleep(15)

Этот код усыпит вашу программу на 15 часов. Также доступны минуты, секунды, дни.  А еще — микросекунды (1/1000,000) и наносекунды (1/1000,000,000).

У класса TimeUnit есть такие свойства:

  • наносекунды: NANOSECONDS
  • микросекунды: MICROSECONDS
  • миллисекунды: MILLISECONDS
  • секунды: SECONDS
  • минуты: MINUTES
  • часы: HOURS
  • дни: DAYS

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

Подробнее можно почитать тут.