Если нам нужно выполнить некоторые простые задачи времени во время нашего процесса программирования, нам не нужно выполнять сложный контроль. Мы можем рассмотреть возможность использования задач времени таймера в JDK для его достижения. В следующем LZ анализирует таймер таймера Java на основе его принципа, примера и дефекта таймера.
1. Введение
В Java полная задача времени должна быть выполнена классами Timer и Timertask. Вот как они определены в API. Таймер: инструмент, который использует его для распоряжения задач, которые потоки выполняют в фоновых потоках позже. Задачи могут быть выполнены один раз, или они могут быть выполнены неоднократно. Задача, запланированная Timertask: Timer как задача, которая выполняется или повторяется. Мы можем понять, что Timer - это инструмент таймера, используемый для планирования выполнения указанных задач в фоновом потоке, и Timertask Abstract Class, подкласс которой представляет собой задачу, которая может быть запланирована Timer.
Таймер класс <br /> В таймере класса инструмента предоставляется четыре метода конструктора. Каждый конструктор запускает поток таймера. В то же время класс таймера может гарантировать, что несколько потоков могут использовать один объект таймера без внешней синхронизации, поэтому класс таймера безопасен для потока. Однако, поскольку каждый объект таймера соответствует одному фоновому потоку, который используется для выполнения всех задач таймера в последовательности, в целом, время, потраченное на выполнение нашей задачи потока, должно быть очень коротким. Однако из -за особых обстоятельств время выполнения определенного задачи таймера слишком длинное, поэтому оно «исключительно» поток выполнения задачи таймера, и все последующие потоки должны ждать его выполнения, что задержит выполнение последующих задач и создаст эти задачи накапливаться вместе. Мы проанализируем конкретную ситуацию позже.
Когда программа инициализирует таймер, задача времени будет выполнена в соответствии со временем, которое мы установили. Таймер предоставляет метод расписания, который имеет несколько перегрузки для адаптации к различным ситуациям, следующим образом:
Расписание (задача Timertask, дата времени): Запланируйте выполнение указанной задачи в указанное время.
График (задача Timertask, дата первого периода, длительный период): Запланируйте указанную задачу, чтобы начать повторное выполнение фиксированной задержки в указанное время.
Расписание (задача Timertask, длинная задержка): планирует выполнять указанную задачу после указанной задержки.
График (задача Timertask, длительная задержка, длительный период): Запланируйте указанную задачу, которая будет выполнена неоднократно фиксированной задержкой после указанной задержки.
В то же время метод PradeAteAtFixEdRate также перегружен. Метод PradeUleatFixEdRate совпадает с графиком, но их фокус отличается, и разница анализируется позже.
ShaduleAtFixedRate (Timertask Task, Date Firstime, Long Period): Запланируйте указанную задачу, которая будет выполнена неоднократно с фиксированной скоростью в указанное время.
ShaduleAtFixedRate (Timertask Задача, длинная задержка, длительный период): Запланируйте указанную задачу, чтобы начать повторное выполнение с фиксированной скоростью после указанной задержки.
Timertask
Класс Timertask - это абстрактный класс, расположенный Timer как задачу, которая выполняется или повторяется. Он имеет абстрактный метод run (), который используется для выполнения операций, которые будут выполнены соответствующей задачей таймера. Следовательно, каждый конкретный класс задач должен наследовать Timertask, а затем переопределять метод run ().
Кроме того, он имеет два неабстрактных метода:
Boolean Cancel (): Отмените эту задачу таймера.
Long PredulleDexecutionTime (): возвращает запланированное время выполнения самого последнего фактического выполнения этой задачи.
2. Примеры
2.1. Укажите время задержки для выполнения задач времени
открытый класс Timertest01 {таймер таймер; public timertest01 (int time) {timer = new Timer (); timer.schedule (new timertasktest01 (), time * 1000); } public static void main (string [] args) {System.out.println ("Timer Begin ..."); новый Timertest01 (3); }} public Class TimerTaskTest01 Extends Timertask {public void run () {System.out.println ("Time's Up !!!"); }} Результаты работы:
Первая печать: таймер начинается ...
Печать за 3 секунды: время вверх !!!
2.2. Выполнить задачи времени в указанное время
открытый класс Timertest02 {таймер таймер; public timertest02 () {date time = gettime (); System.out.println ("Укажите время времени =" + time); timer = new Timer (); timer.schedule (new timertasktest02 (), time); } public date getTime () {календарный календарь = календарь.getInstance (); calendar.set (calendar.hour_of_day, 11); Calendar.Set (Calendar.minute, 39); Calendar.Set (Calendar.second, 00); Дата времени = календарь.gettime (); Время возвращения; } public static void main (string [] args) {new timertest02 (); }} public Class TimerTaskTest02 Extends TimerTask {@Override public void run () {System.out.println ("Заполнение потоков в указанное время ..."); }} Когда время достигнет 11:39:00, задача потока будет выполнена, конечно, оно будет выполнено, даже если оно больше этого времени! ! Результат исполнения:
Указанное время = вторник 10 июня 11:39:00 CST 2014
Выполнить задачи потока в указанное время ...
2.3. После отложенности указанного времени задача времени будет выполнена в указанное время интервала.
открытый класс Timertest03 {таймер таймер; public timertest03 () {timer = new Timer (); timer.schedule (новый TimertaskTest03 (), 1000, 2000); } public static void main (string [] args) {new timertest03 (); }} public class TimerTaskTest03 Extends TimerTask {@Override public void run () {дата дата = новая дата (this.scheduledexecutiontime ()); System.out.println («Время для выполнения этого потока:» + date); }} Результаты работы:
Время для выполнения этой ветки: Tue 10 июня 21:19:47 CST 2014
Время для выполнения этой ветки: Tue 10 июня 21:19:49 CST 2014
Время для выполнения этой ветки: Tue 10 июня 21:19:51 CST 2014
Время для выполнения этой ветки: Tue 10 июня 21:19:53 CST 2014
Время для выполнения этой ветки: Tue 10 июня 21:19:55 CST 2014
Время для выполнения этой ветки: Tue 10 июня 21:19:57 CST 2014
................
Для этой задачи, если мы не остановим задачу, она продолжит работать.
Для приведенных выше трех примеров LZ просто кратко продемонстрировал это и не объяснил пример метода PradeAteFixEdrate. На самом деле, этот метод такой же, как метод расписания!
2.4. Анализ расписания и PradeAteAtFixEdRate
1), Расписание (задача Timertask, дата времени), расписание (задача Timertask, длинная задержка)
Для обоих методов, если указанный PredulleDexecutionTime <= SystemCurrentTime, задача будет выполнена немедленно. DecaduLeDexecutition Time не изменится из -за чрезмерного выполнения задачи.
2) Расписание (задача Timertask, дата первого периода, длительный период), график (задача Timertask, длинная задержка, длительный период)
Эти два метода немного отличаются от двух вышеуказанных. Как упоминалось ранее, задача таймера таймера будет отложена, потому что предыдущая задача выполняется в течение длительного времени. В этих двух методах запланированное время каждой выполняемой задачи будет изменяться с фактическим временем предыдущей задачи, то есть PhareDexeCutionTime (n+1) = realectcutiontime (n)+период времени. То есть, если NTH -задача вызывает этот процесс выполнения из -за какой -то ситуации, и, наконец, SystemCurrentTime> = PredulleDexecutionTime (n+1), это задача n+1 и не будет выполнена из -за времени. Он будет ждать выполнения NTH -задачи до выполнения, тогда это неизбежно приведет к выпуску и изменению реализации выполнения N+2. Следовательно, эти два метода уделяют больше внимания стабильности времени хранения.
3) SeduleAtFixedRate (задача Timertask, дата первого периода, длительный период), PradeAteFixedRate (задача Timertask, длинная задержка, длительный период)
Как упоминалось ранее, в центре внимания методов PradeAteFixedRate и расписания отличается. Метод расписания фокусируется на стабильности времени сбережений, в то время как метод PradeAteAtFixEdRate больше фокусируется на поддержании стабильности частоты выполнения. Почему вы так говорите, причины заключаются в следующем. В методе расписания задержка предыдущей задачи приведет к задержке задачи времени после него, в то время как метод PradeAteAtFixEdRate не будет. Если время выполнения NTH Задача слишком длинное, SystemCurrentTime> = PredulleDexeCutionTime (n+1), не будет немедленно ожидания, пока она не будет выполнить задачу n+1. Следовательно, метод расчета времени выполнения метода PradeAteFixedRate отличается от графика, но PredulleDexecutionTime (n) = FirstExeCuteTime +N*период времени, и метод расчета останется неизменным навсегда. Поэтому PradeuLeatFixEdRate больше фокусируется на поддержании стабильной частоты выполнения.
3. дефекты таймера
3.1. Дефекты таймера
Таймер таймера может времени (выполнять задачи в указанное время), задержка (задачи задержки через 5 секунд) и периодически выполнять задачи (выполнять задачи в 1 секунду), но у таймера есть некоторые недостатки. Прежде всего, поддержка Таймера для планирования основана на абсолютном времени, а не на относительном времени, поэтому он очень чувствителен к изменениям в системном времени. Во -вторых, поток таймера не поймает исключения. Если неконтролируемое исключение брошено Timertask, это приведет к прекращению таймера. В то же время таймер не возобновит выполнение потока, и он ошибочно полагает, что весь поток таймера будет отменен. В то же время, Timertask, который был запланирован еще не выполнен, больше не будет выполняться, а новые задачи не могут быть запланированы. Следовательно, если Timertask бросит неконтролируемое исключение, таймер приведет к непредсказуемому поведению.
1) Дефект задержки управления таймером <br /> Предыдущий таймер создаст только одну задачу потока при выполнении временной задачи. Если есть несколько потоков, если один из потоков приводит к тому, что время выполнения задачи потока по какой -то причине будет слишком длинным, а интервал между двумя задачами превышает время между ними, возникнут некоторые дефекты: произойдут некоторые дефекты:
открытый класс Timertest04 {частный таймер таймера; общественное долгое начало; public timertest04 () {this.timer = new Timer (); start = System.CurrentTimeMillis (); } public void -timerone () {timer.schedule (new timertask () {public void run () {System.out.println ("Вызов Timerone, Time:" + (System.currentTimeMillis () - Start); try {thread.sleep (4000); // Thread Sleeps 3000} CALLED (ERTERPECTEXCECEPTEXTEXCEPTEX ERCECEXTEXCECTEX e); }}}}, 1000); } public void timertwo () {timer.schedule (new timertask () {public void run () {System.out.println ("Вызов Timerone, Time:" + (System.currentTimeMillis () - start));}}, 3000); } public static void main (string [] args) бросает исключение {timertest04 test = new timertest04 (); test.timerone (); test.imertwo (); }} Согласно нашему нормальному мышлению, Timertwo должен быть выполнен после 3S, и результат должен быть:
Timerone призван, время: 1001
Назвук Timerone, время: 3001
Но все пошло против моих ожиданий. Timerone спит (4000), спит 4S, а таймер находится внутри таймера, что вызывает время, необходимое для превышения интервала Timeone. Результат:
Назвук Timerone, время: 1000
Timerone призван, время: 5000
2) Дефект исключений отбрасывает таймер
Если Timertask бросит Runtimeexception, таймер прекратит все задачи. следующее:
открытый класс Timertest04 {частный таймер таймера; public timertest04 () {this.timer = new Timer (); } public void -timerone () {timer.schedule (new timertask () {public void run () {throw new runtimeexception ();}}, 1000); } public void timertwo () {timer.schedule (new timertask () {public void run () {System.out.println ("Я выполняю его?");}}, 1000); } public static void main (string [] args) {timertest04 test = new timertest04 (); test.timerone (); test.imertwo (); }} Результат работы: Timerone бросает исключение, что приводит к прекращению задачи Timertwo.
Исключение в ветке "timer-0" java.lang.runtimeexception в com.chenssy.timer.timertest04 $ 1.run (timertest04.java:25) на java.util.timerthread.mainloop (Timer.java:555) на java.util.timerthread.run (Timer.java:555) на java.util.timerthread.
Для дефектов таймера мы можем считать reduledThreadPoolexeCutor в качестве замены. Таймер основан на абсолютном времени и более чувствителен к системному времени, в то время как PredultHreadPoolexeCutor основан на относительном времени; Timer - это единственный поток внутри, в то время как PredulledThreadPoolexeCutor - это пул потоков внутри, поэтому он может поддерживать одновременное выполнение нескольких задач.
3.2. Заменить таймер на cheduledExecutorservice
1) Решите проблему один:
public Class PredicleDexeCutortest {private PredulleDexeCutorService preduexec; общественное долгое начало; WarededExecutortest () {this.scheduexec = executors.newschedudThreadpool (2); this.start = system.currenttimemilsis (); } public void -timerone () {praduexec.schedule (new Runnable () {public void run () {System.out.println ("Timerone, Time:" + (System.currentTimeMillis () - start); try {thread.sleep (4000);} Catch (ErruptureException e) {e.print ttrace); }, 1000, timeUnit.milliseconds); } public void timertwo () {shaduleExec.schedule (new Runnable () {public void run () {System.out.println ("Timertwo, Time:" + (System.currentTimeMillis () - start));}}, 2000, timeUnit.milliseconds); } public static void main (string [] args) {preduledExecutortest test = new goodledexeCutortest (); test.timerone (); test.imertwo (); }} Результаты работы:
Timerone, время: 1003
Timertwo, The Time: 2005
2) решить проблему две
public Class PredicleDexeCutortest {private PredulleDexeCutorService preduexec; общественное долгое начало; WarededExecutortest () {this.scheduexec = executors.newschedudThreadpool (2); this.start = system.currenttimemilsis (); } public void timerone () {praduexec.schedule (new Runnable () {public void run () {throw new runtimeexception ();}}, 1000, timeUnit.milliseconds); } public void timertwo () {shaduleExec.scheduleatfixedrate (new Runnable () {public void run () {System.out.println ("Timertwo вызывает .....");}}, 2000 500, TimeUnit.milliseconds); } public static void main (string [] args) {preduledExecutortest test = new goodledexeCutortest (); test.timerone (); test.imertwo (); }} Результаты работы:
Timertwo призвал ... Timertwo призвал ... Timertwo призвал ... Timertwo призвал ... Timertwo призвал ... Timertwo призвал ... Timertwo призвал ... Timertwo призвал ... Timertwo вызвал ... Timertwo вызвал ............ Timertwo вызывает .......................
Вышеуказанное - все содержание этой статьи. Это все о задачах времени Java. Я надеюсь, что это будет полезно для вашего обучения.