Главная » Java » Timer и TimerTask

0

 

  Класс Timer предоставляет средства управления заданиями во времени, включая обслуживание повторяющихся событий. Каждому объекту Timer ставится в соответствие поток вычислений, который запускается на выполнение, когда   наступает   момент   активизации   любого   из   соответствующих   объектов TierTask. Следующий фрагмент кода, например, с периодичностью один раз в секунду осуществляет вывод на экран информации об использовании оперативной памяти виртуальной машиной Java:

 

Timer timer = new Timer(true);

timer.scheduleAtFixedRate(new MemorywatchTask(),   0,   1000);

Вначале создается новый объект Timer, ответственный за поддержку расписания выполнения задания, описываемого объектом класса MemoryWatchTask (текст класса MemoryWatchTask приведен чуть ниже). Аргумент true, передаваемый конструктору объекта Timer, указывает, что объектом должен использоваться поток-демон (daemon) (см. раздел 10.9), так что по завершении деятельности всех пользовательских (user) потоков вычислений будет автоматически остановлен и поток, выполняющий мониторинг памяти.

   Вызов метода scheduleAtFixedRate устанавливает расписание выполнения задания MemoryWatchTask с периодичностью один раз в секунду (значение третьего параметра равно 1000 миллисекунд) и без задержек (содержимое второго параметра равно 0). Объект Timer, руководствуясь характеристиками заданного расписания, непосредственно обращается к методу run объекта MemoryWatchTask:

 

import java.util.TimerTask;

import Java.util.Date;

 

public class MemoryWatchTask extends TimerTask {

       public void  run()   {

 ");

          System.out.print(new Date()  + ":   " );

          Runtime  rt = Runtime.getRuntime();

          System.out.print(rt.freeMemory()  + "  свободно, “);

          System.out.print(rt.totalMemory()  + " всего");

          System.out. println();

   }

}

 

 Класс MemoryWatchTask, производный от абстрактного типа TimerTask, определяет задание, которое заключается в выводе на экран текущих даты/времени и значений свободного и общего объемов памяти. Класс TimerTask реализует интерфейс Runnable, и его метод run — это именно тот фрагмент кода, к которому обращается объект Timer в момент времени, регламентируемый заданным расписанием. Поскольку в данном случае расписание предусматривает выполнение задания один раз в секунду, поток вычислений, используемый объектом timer, должен находиться в состоянии ожидания между отдельными сеансами работы задания MemoryWatchTask в течение не более одной секунды.

В составе класса TimerTask объявлены три метода, описанных ниже.

 

public abstract void  run()

Определяет     набор     операций,     осуществляемых     текущим     объектом

TimerTask.

public boolean cancel()

Аннулирует задание, определяемое текущим объектом TimerTask, так ч далее оно выполняться не будет (либо не будет выполнено ни разу, е прежде метод run еще не вызывался). Возвращает значение true, если данное  расписание  предусматривало  периодическое   выполнение  задан либо разовый вызов  run, который еще не был осуществлен.  Возвращает значение false, если задание уже выполнялось в рамках разового расписания (once-only scheduling), либо еще не включалось в какое бы то ни было расписание, либо аннулировалось раньше. Метод по существу возвращает true в тех ситуациях, когда он препятствует выполнению задания в соответствии с расписанием.

 

 

public long scheduledExecutionTime()

Возвращает величину продолжительности предыдущего (возможно, и текущего) сеанса выполнения задания TimerTask. Результат представляется в миллисекундах. Наиболее часто метод вызывается изнутри кода run с целью проверки того, достаточно ли велик доступный временной интервал для завершения текущего сеанса выполнения задания в условиях расписания с фиксированным расходом времени (fixed-rate scheduling). Если момент начала сеанса откладывается на слишком продолжительный период времени, код метода run вправе принять решение о том, чтобы не выполнять текущий сеанс вовсе.

  Разрешается аннулировать отдельное задание либо отменить расписание целиком, вызвав метод cancel объекта Timer. В первом случае предполагается, что конкретное задание больше не должно выполняться. Вызов метода cancel объекта Timer препятствует выполнению им любых заданий в будущем.

  Каждому объекту Timer ставится в соответствие единственный поток вычислений,   управляющий   сеансами   выполнения   задания.   Разновидность   потока можно задать с помощью конструктора.

 

 public Timer(boolean isDaemon)

Создает новый объект Timer; если значение параметра isDaemon равно true, поток вычислений, принадлежащий объекту, будет относиться к категории потоков-демонов.

 public Timer()

Конструктор аналогичен предыдущему при условии Timer(false).

 

  Если для создания объекта Timer применяется конструктор без параметров, объект получит в свое распоряжение пользовательский поток. Работа такого потока будет завершена только в том случае, когда не существует заданий, подлежащих выполнению, и объект Timer не достижим, т.е. все ссылки на него отсутствуют. Всецело полагаться на подобное поведение системы не следует, поскольку оно зависит только от способности и "желания" сборщика мусора выявлять факт недостижимости объектов Timer, а это может произойти в любое время либо не произойти вовсе.

  Существуют три разновидности расписаний, поддерживаемых объектами Timer. При использовании разового расписания задание должно быть выполнено только единожды. Расписание с фиксированным интервалом задержки (fixed-delay scheduling) позволяет установить величину промежутка времени между Моментами начала соседних сеансов обслуживания задания. Любая задержка начала одного сеанса, обусловленная общим расписанием работы потоков либо Происшедшая по вине сборщика мусора или иного фонового процесса, приводит к сдвигу моментов начала всех остальных сеансов, так что момент старта сеанса определяется только тем, когда начал выполняться предыдущий сеанс. Расписание с фиксированным расходом времени отличается тем, что момент начала выполнения  каждого  сеанса  обслуживания   задания   "привязывается"   к   моменту старта первого сеанса. Если выполнение сеанса по каким-либо причинам откладывается, промежуток времени, остающийся до момента начала следующего сеанса, сужается или даже сокращается до нуля — это зависит от величины периода и продолжительности обслуживания задания. Расписания с фиксированным интервалом задержки находят применение в тех случаях, когда существенным фактором является частота выполнения заданий (примером может служить задание, связанное с отображением отдельных кадров анимационной последовательности). Расписания же с фиксированным расходом времени используются в тех обстоятельствах, когда важно обеспечить привязку сеансов к абсолютным моментам времени.

   Ниже кратко рассмотрены основные методы, объявленные в составе класса Timer.

 

 public void schedule(TimerTask task,  Date time)

Устанавливает разовое расписание  выполнения  задания  task  в  момент времени, определяемый значением time.

 public void schedule(TimerTask task,  long delay)

Устанавливает разовое расписание выполнения задания task по истечении промежутка времени delay, исчисляемого в миллисекундах.

 public void scheduleOrimerTask task,  Date firstTime,  long period)

Устанавливает расписание с фиксированным интервалом задержки,  предусматривающее выполнение задания task каждые period миллисекунд, начиная с момента времени fi rstTime вплоть до завершения посредством cancel.

 public void schedule(TimerTask task,  long delay,  long period)

Устанавливает расписание с фиксированным интервалом задержки, предусматривающее выполнение задания task по истечении промежутка времени delay, а затем каждые period миллисекунд вплоть до завершения посредством cancel.

public void scheduleAtFixedRate(TimerTask task,  Date firstTime, long period)

Устанавливает расписание с фиксированным расходом времени, предусматривающее выполнение задания task каждые period миллисекунд, начиная с момента времени fi rstTime вплоть до завершения посредством cancel.

 public void scheduleAtFixedRate(TimerTask task,  long delay, long period)

Устанавливает расписание с фиксированным расходом времени, предусматривающее выполнение задания task по истечении промежутка времени delay, а затем каждые period миллисекунд вплоть до завершения посредством cancel.

   Если при вызове любого из методов, предусматривающих задание начального момента времени, этот момент уже прошел, сеанс обслуживания задания будет начат немедленно. Все значения временных интервалов измеряются в миллисекундах — для преобразования содержимого объекта Date в значение, выраженное в миллисекундах, может быть использован метод getTime класса Date (за подробностями обращайтесь к разделу 19.3) — и являются при ближенными, поскольку для вычисления моментов начала будущих сеансов о служивания задания объект Timer пользуется методом Thread.wait(long), метод wait, как известно (см. раздел 10.5), — точно так же как и sleep (см. раздел 10.6) — не способен обеспечить сколько-нибудь полных гарантий точности. Если величина промежутка времени ожидания настолько велика, что сложение ее со значением текущего времени приводит к переполнению разрядной сетки переменной типа long, будет выброшено исключение типа illegalArgumentException.

   Объект TimerTask может управляться не более чем одним объектом Timer, a объект Timer, расписание которого было отменено вызовом cancel, впредь не способен поддерживать новые расписания. Попытка нарушения любого из названных ограничивающих правил либо повторное включение в расписание задания TimerTask, ранее аннулированного вызовом cancel, приводят к выбрасыванию исключения типа illegalStateException.

  Управление потоками вычислений, принадлежащими объектам Timer (наряду со всеми другими потоками), является прерогативой исполняющей системы; способов изменения приоритета потока средствами объекта Timer не существует — поток приобретает тот же приоритет, которым обладает поток-инициатор, создающий объект Timer. Если необходимо повысить приоритет потока в период выполнения им определенного задания TimerTask, это может быть сделано внутри кода соответствующего метода run. Если же возникает потребность в повышении приоритета потока Timer как такового, следует создавать объект Timer в среде того потока, который уже обладает нужным уровнем приоритета.

  Средства определения того, какие задания обслуживаются конкретным объектом Timer, отсутствуют.

 

Источник: Арнолд, Кен, Гослинг, Джеймс, Холмс, Дэвид. Язык программирования Java. 3-е изд .. : Пер. с англ. – М. : Издательский дом «Вильяме», 2001. – 624 с. : ил. – Парал. тит. англ.

По теме:

  • Комментарии