Я хотел бы иметь java.utils.Timer со сбрасываемым временем в java. Мне нужно установить однократное отключение события через X секунд. Если между временем создания таймера и X секунд ничего не происходит, событие происходит как обычно.
Если, однако, до истечения X секунд я решаю, что событие должно произойти через Y секунд, тогда я хочу иметь возможность указать таймеру, чтобы он сбросил свое время, чтобы событие произошло через Y секунд. Например. таймер должен уметь делать что-то вроде:
Timer timer = new Timer();
timer.schedule(timerTask, 5000); //Timer starts in 5000 ms (X)
//At some point between 0 and 5000 ms...
setNewTime(timer, 8000); //timerTask will fire in 8000ms from NOW (Y).
Я не вижу способа сделать это с помощью таймера utils, так как если вы вызовете cancel (), вы не сможете запланировать его снова.
Единственный способ, которым я приблизился к воспроизведению этого поведения, - это использование javax.swing.Timer, который включает остановку исходного таймера и создание нового. то есть:
timer.stop();
timer = new Timer(8000, ActionListener);
timer.start();
Есть способ попроще ??




Вам нужно запланировать повторяющуюся задачу? В этом случае я рекомендую вам рассмотреть возможность использования Кварцевый.
Я не думаю, что это возможно сделать с Timer/TimerTask, но в зависимости от того, чего именно вы хотите достичь, вы можете быть довольны использованием java.util.concurrent.ScheduledThreadPoolExecutor.
Согласно документации Timer, начиная с Java 1.5, вы должны предпочесть ScheduledThreadPoolExecutor. (Вы можете создать этот исполнитель, используя Executors.newSingleThreadScheduledExecutor() для простоты использования; он создает что-то очень похожее на Timer.)
Замечательно то, что когда вы планируете задачу (вызывая schedule()), она возвращает объект ScheduledFuture. Вы можете использовать это, чтобы отменить запланированную задачу. Затем вы можете отправить новую задачу с другим временем запуска.
ETA: Связанная с Timer документация ничего не говорит о ScheduledThreadPoolExecutor, однако в версии OpenJDK было сказано следующее:
Java 5.0 introduced the
java.util.concurrentpackage and one of the concurrency utilities therein is theScheduledThreadPoolExecutorwhich is a thread pool for repeatedly executing tasks at a given rate or delay. It is effectively a more versatile replacement for theTimer/TimerTaskcombination, as it allows multiple service threads, accepts various time units, and doesn't require subclassingTimerTask(just implementRunnable). ConfiguringScheduledThreadPoolExecutorwith one thread makes it equivalent toTimer.
Проблема с этим подходом заключается в том, что у вас больше нет доступа к TimerTask.scheduledExecutionTime() внутри вашей задачи. Вы не сможете определить, является ли задача «запоздалой» и не должна ли выполняться.
используйте myScheduledThreadPoolExecutor.getQueue().clear() для удаления всех запланированных задач, которые еще не запущены, но вы не можете использовать этот метод с Executors.newSingleThreadScheduledExecutor() вместо этого, вы должны создать экземпляр new ScheduledThreadPoolExecutor(1), потому что только методы интерфейса доступны для объекта, возвращаемого Executor.
Вместо предложения @gMale используйте executor.setRemoveOnCancelPolicy(true);
Если вашему Timer нужно будет выполнить только одну задачу, я бы предложил разделить ее на подклассы:
import java.util.Timer;
import java.util.TimerTask;
public class ReschedulableTimer extends Timer
{
private Runnable task;
private TimerTask timerTask;
public void schedule(Runnable runnable, long delay)
{
task = runnable;
timerTask = new TimerTask()
{
@Override
public void run()
{
task.run();
}
};
this.schedule(timerTask, delay);
}
public void reschedule(long delay)
{
timerTask.cancel();
timerTask = new TimerTask()
{
@Override
public void run()
{
task.run();
}
};
this.schedule(timerTask, delay);
}
}
Вам нужно будет поработать над кодом, чтобы добавить проверки на неправильное использование, но он должен достичь желаемого. Похоже, что ScheduledThreadPoolExecutor не имеет встроенной поддержки для изменения расписания существующих задач, но аналогичный подход должен работать и там.
это то, что я пробую. У меня есть класс, который опрашивает базу данных каждые 60 секунд с помощью TimerTask.
в моем основном классе я сохраняю экземпляр Timer и экземпляр моего локального подкласса TimerTask. у основного класса есть метод для установки интервала опроса (скажем, от 60 до 30). в нем я отменяю свою TimerTask (это мой подкласс, в котором я перезаписал метод cancel (), чтобы выполнить некоторую очистку, но это не имеет значения), а затем сделаю его нулевым. Я воссоздаю его новый экземпляр и планирую новый экземпляр с новым интервалом в существующем таймере.
поскольку сам Timer не отменяется, поток, который он использовал, остается активным (как и любые другие TimerTasks внутри него), а старый TimerTask заменяется новым, который оказывается таким же, но VIRGIN (поскольку старый был бы выполнен или запланирован, он больше не является VIRGIN, как требуется для планирования).
когда я хочу выключить весь таймер, я отменяю и обнуляю TimerTask (то же самое, что я сделал при изменении времени, опять же, для очистки ресурсов в моем подклассе TimerTask), а затем я отменяю и обнуляю сам таймер.
Весь фрагмент кода выглядит так ... Надеюсь, он поможет полностью
{
Runnable r = new ScheduleTask();
ReschedulableTimer rescheduleTimer = new ReschedulableTimer();
rescheduleTimer.schedule(r, 10*1000);
public class ScheduleTask implements Runnable {
public void run() {
//Do schecule task
}
}
class ReschedulableTimer extends Timer {
private Runnable task;
private TimerTask timerTask;
public void schedule(Runnable runnable, long delay) {
task = runnable;
timerTask = new TimerTask() {
public void run() {
task.run();
}
};
timer.schedule(timerTask, delay);
}
public void reschedule(long delay) {
System.out.println("rescheduling after seconds "+delay);
timerTask.cancel();
timerTask = new TimerTask() {
public void run() {
task.run();
}
};
timer.schedule(timerTask, delay);
}
}
}
Вот пример сбрасываемого таймера. Попробуйте изменить его для вашей убедительности ...
package com.tps.ProjectTasks.TimeThread;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
/**
* Simple demo that uses java.util.Timer to schedule a task to execute
* every 5 seconds and have a delay if you give any input in console.
*/
public class DateThreadSheduler extends Thread {
Timer timer;
BufferedReader br ;
String data = null;
Date dNow ;
SimpleDateFormat ft;
public DateThreadSheduler() {
timer = new Timer();
timer.schedule(new RemindTask(), 0, 5*1000);
br = new BufferedReader(new InputStreamReader(System.in));
start();
}
public void run(){
while(true){
try {
data =br.readLine();
if (data != null && !data.trim().equals("") ){
timer.cancel();
timer = new Timer();
dNow = new Date( );
ft = new SimpleDateFormat ("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
System.out.println("Modified Current Date ------> " + ft.format(dNow));
timer.schedule(new RemindTask(), 5*1000 , 5*1000);
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String args[]) {
System.out.format("Printint the time and date was started...\n");
new DateThreadSheduler();
}
}
class RemindTask extends TimerTask {
Date dNow ;
SimpleDateFormat ft;
public void run() {
dNow = new Date();
ft = new SimpleDateFormat ("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
System.out.println("Current Date: " + ft.format(dNow));
}
}
Этот пример печатает текущую дату и время каждые 5 секунд ... Но если вы введете какой-либо ввод в консоли, таймер будет отложен для выполнения данной задачи ввода ...
Я сделал собственный класс таймера для той же цели; не стесняйтесь использовать это:
public class ReschedulableTimer extends Timer {
private Runnable mTask;
private TimerTask mTimerTask;
public ReschedulableTimer(Runnable runnable) {
this.mTask = runnable;
}
public void schedule(long delay) {
if (mTimerTask != null)
mTimerTask.cancel();
mTimerTask = new TimerTask() {
@Override
public void run() {
mTask.run();
}
};
this.schedule(mTimerTask, delay);
}
}
ScheduledThreadPoolExecutor обсуждается в этом таймере: developer.android.com/reference/java/util/Timer.html