The Timer (java.util.Timer) doc describes the cancel method as one that affects the Timer and it states that the timer cannot be used after cancellation. So I instantiate a new Timer. Why will it not let me re-use the argument task0 in this example? I'm not even invoking purge which is described as making tasks GC-eligible. Until it might be explained to be otherwise, I claim Timer class should not affect a TimerTask object that is merely an argument to it.
import java.util.Timer;
import java.util.TimerTask;
public class Tester {
public static void main(String[] args) throws InterruptedException {
long delay = 3000L;
Timer timer0 = new Timer();
Task task0 = new Task();
timer0.schedule(task0, delay);
timer0.cancel();
Timer timer1 = new Timer();
timer1.schedule(task0, delay); // throws an exception if we use task0
Thread.sleep(5000);
timer1.cancel();
}
}
class Task extends TimerTask {
Task() {
}
#Override
public void run() {
System.out.println("task was invoked");
}
}
Allowing this would be error prone, since task0 could still be running when scheduled again by another timer. (Note that cancel() does not terminate the task.)
Note that if task0 is managed by a single Timer, the same task will never be executed concurrently with itself (regardless if it is executed with fixed-delay or with fixed-rate).
If you really want such behavior, the work around would be to let task0 and a task1 wrap a common object:
class Task extends TimerTask {
Runnable runnable;
Task(Runnable runnable) {
this.runnable = runnable;
}
#Override
public void run() {
runnable.run();
}
}
And then execute it like this:
// "Wrapped" (and thus shared) by task0 and task1 below.
Runnable runnable = new Runnable() {
#Override
public void run() {
System.out.println("task was invoked");
}
}
Timer timer0 = new Timer();
Task task0 = new Task(runnable);
timer0.schedule(task0, delay);
timer0.cancel();
Task task1 = new Task(runnable);
Timer timer1 = new Timer();
timer1.schedule(task1, delay); // throws an exception if we use task0
Thread.sleep(5000);
timer1.cancel();
Take a look:
http://www.docjar.com/html/api/java/util/TimerTask.java.html
http://www.docjar.com/html/api/java/util/Timer.java.html
The TimerTask class is just a thin extension of Runnable which tracks a bit of metadata about scheduling (namely: next execution time). But, if you schedule it on two timers, there's still only one next execution field, so one timer would overwrite the next execution time of the other, which is almost certainly not what you want, so it tracks that it's been scheduled before, and throws an exception in Timer, instead.
If it allowed this, you'd get rather unexpected behavior.
This also is a problem if a timer task wants to re-schedule itself in the same Timer - maybe with a different delay this time.
This would allow me for example to implement something like an exponential backoff algorithm (retry a task, with exponentially growing delays.
It seems such a timer task with variable delays can be most comfortably implemented by using a ScheduledExecutorService, because this class does not pose such restrictions.
Alternatively, you can create a method to return the same task and then schedulde it to the same timer or different timers:
import java.util.Timer;
import java.util.TimerTask;
public class Tester {
public static void main(String[] args) throws InterruptedException {
long delay = 3000L;
Timer timer0 = new Timer();
timer0.schedule(createTask(), delay);
Timer timer1 = new Timer();
timer1.schedule(createTask(), delay);
Thread.sleep(5000);
timer1.cancel();
// purge all canceled tasks from timers
timer0.purge();
timer1.purge();
}
}
Task createTask() {
Task task0 = new Task();
return task0;
}
class Task extends TimerTask {
Task() {
}
#Override
public void run() {
System.out.println("task was invoked");
// here do something
cancel(); // stop it.
}
}
Related
I have a thread which is in charge of doing some processes. I want make it so that these processing would be done every 3 seconds. I've used the code below but when the thread starts, nothing happens.
I assumed that when I define a task for my timer it automatically execute the ScheduledTask within time interval but it doesn't do anything at all.
What am I missing?
class temperatureUp extends Thread
{
#Override
public void run()
{
TimerTask increaseTemperature = new TimerTask(){
public void run() {
try {
//do the processing
} catch (InterruptedException ex) {}
}
};
Timer increaserTimer = new Timer("MyTimer");
increaserTimer.schedule(increaseTemperature, 3000);
}
};
A few errors in your code snippet:
You extend the Thread class, which is not really good practice
You have a Timer within a Thread? That doesnt make sense as the a Timer runs on its own Thread.
You should rather (when/where necessary), implement a Runnable see here for a short example, however I cannot see the need for both a Thread and Timer in the snippet you gave.
Please see the below example of a working Timer which will simply increment the counter by one each time it is called (every 3seconds):
import java.util.Timer;
import java.util.TimerTask;
public class Test {
static int counter = 0;
public static void main(String[] args) {
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
System.out.println("TimerTask executing counter is: " + counter);
counter++;//increments the counter
}
};
Timer timer = new Timer("MyTimer");//create a new Timer
timer.scheduleAtFixedRate(timerTask, 30, 3000);//this line starts the timer at the same time its executed
}
}
Addendum:
I did a short example of incorporating a Thread into the mix. So now the TimerTask will merely increment counter by 1 every 3 seconds, and the Thread will display counters value sleeping for 1 seconds every time it checks counter (it will terminate itself and the timer after counter==3):
import java.util.Timer;
import java.util.TimerTask;
public class Test {
static int counter = 0;
static Timer timer;
public static void main(String[] args) {
//create timer task to increment counter
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
// System.out.println("TimerTask executing counter is: " + counter);
counter++;
}
};
//create thread to print counter value
Thread t = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
System.out.println("Thread reading counter is: " + counter);
if (counter == 3) {
System.out.println("Counter has reached 3 now will terminate");
timer.cancel();//end the timer
break;//end this loop
}
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
});
timer = new Timer("MyTimer");//create a new timer
timer.scheduleAtFixedRate(timerTask, 30, 3000);//start timer in 30ms to increment counter
t.start();//start thread to display counter
}
}
import java.util.Timer;
import java.util.TimerTask;
public class ThreadTimer extends TimerTask{
static int counter = 0;
public static void main(String [] args) {
Timer timer = new Timer("MyTimer");
timer.scheduleAtFixedRate(new ThreadTimer(), 30, 3000);
}
#Override
public void run() {
// TODO Auto-generated method stub
System.out.println("TimerTask executing counter is: " + counter);
counter++;
}
}
In order to do something every three seconds you should use scheduleAtFixedRate (see javadoc).
However your code really does nothing because you create a thread in which you start a timer just before the thread's run stops (there is nothing more to do). When the timer (which is a single shoot one) triggers, there is no thread to interrupt (run finished before).
class temperatureUp extends Thread
{
#Override
public void run()
{
TimerTask increaseTemperature = new TimerTask(){
public void run() {
try {
//do the processing
} catch (InterruptedException ex) {}
}
};
Timer increaserTimer = new Timer("MyTimer");
//start a 3 seconds timer 10ms later
increaserTimer.scheduleAtFixedRate(increaseTemperature, 3000, 10);
while(true) {
//give it some time to see timer triggering
doSomethingMeaningful();
}
}
I think the method you've used has the signature schedule(TimerTask task, long delay) . So in effect you're just delaying the start time of the ONLY execution.
To schedule it to run every 3 seconds you need to go with this method schedule(TimerTask task, long delay, long period) where the third param is used to give the period interval.
You can refer the Timer class definition here to be of further help
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Timer.html
Timer & TimerTask are legacy
The Timer & TimerTask classes are now legacy. To run code at a certain time, or to run code repeatedly, use a scheduled executor service.
To quote the Timer class Javadoc:
Java 5.0 introduced the java.util.concurrent package and one of the concurrency utilities therein is the ScheduledThreadPoolExecutor which is a thread pool for repeatedly executing tasks at a given rate or delay. It is effectively a more versatile replacement for the Timer/TimerTask combination, as it allows multiple service threads, accepts various time units, and doesn't require subclassing TimerTask (just implement Runnable). Configuring ScheduledThreadPoolExecutor with one thread makes it equivalent to Timer.
Executor framework
In modern Java, we use the Executors framework rather than directly addressing the Thread class.
Define your task as a Runnable or Callable. You can use compact lambda syntax seen below. Or you can use conventional syntax to define a class implementing the Runnable (or Callable) interface.
Ask a ScheduledExecutorService object to execute your Runnable object’s code every so often.
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor() ;
Runnable task = () -> {
System.out.println( "Doing my thing at: " + Instant.now() );
};
long initialDelay = 0L ;
long period = 3L ;
TimeUnit timeUnit = TimeUnit.SECONDS ;
scheduledExecutorService.submit( task , initialDelay, period , timeUnit ) ;
…
scheduledExecutorService.shutdown() ; // Stops any more tasks from being scheduled.
scheduledExecutorService.awaitTermination() ; // Waits until all currently running tasks are done/failed/canceled.
Notice that we are not directly managing any Thread objects in the code above. Managing threads is the job of the executor service.
Tips:
Always shutdown your executor service gracefully when no longer needed, or when your app exits. Otherwise the backing thread pool may continue indefinitely like a zombie 🧟♂️.
Consider wrapping your task's working code in a try-catch. Any uncaught exception or error reaching the scheduled executor service results in silently halting the further scheduling of any more runs.
How would I create a thread that will execute after a delay of s seconds?
I would like other processes to run while the thread is waiting.
For example, I would like to create the thread, then print out several other strings, then after s seconds, the thread will run.
What I don't need is the whole program to wait for s seconds, then everything happens. I need processes to run while the delay is ticking.
Thanks!
~Java preferred
Use a ScheduledExecutorService. See the example below.
System.out.println("some stuff");
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
final Runnable task = new Runnable() {
#Override
public void run() {
System.out.println("do something");
}
};
Future<?> futureHandle = scheduler.scheduleWithFixedDelay(task, 10, 10, TimeUnit.SECONDS);
System.out.println("some other stuff");
The task is scheduled with a fixed delay of 10 seconds, so you'll get output for the print statements not in the Runnable followed by the one in the Runnable every 10 seconds.
The output in this example is
some stuff
some other stuff
do something
do something
...
with the "do something" lines occurring at 10 sec. intervals after an initial 10 sec. delay.
To stop it, you can create a "stop" task to put some kind of logic in, and register that.
final Runnable stopTask = new Runnable() {
#Override
public void run() {
futureHandle.cancel(true); // true: interrupt if necessary
}
};
long delay = // some number, how long to wait before invoking the stop task
scheduler.schedule(stopTask, delay, TimeUnit.SECONDS).get(); // wait if necessary and get the future result
scheduler.shutdown(); // shutdown on completion
EDIT
If you just need the task to run once, as pointed out in the comments, consider a TimerTask:
final Timer timer = new Timer();
final TimerTask task = new TimerTask() {
#Override
public void run() {
System.out.println("timer task");
timer.cancel(); // stop timer after execution
}
};
timer.schedule(task, 1000); // schedule task with delay of 1000ms
I would suggest you to take look into quartz scheduler. This is very powerful and does almost similar tasks like unix cron in java environment.
There are bunch of tutorials online for quartz that you can always look into.
Here is one working example with Thread.sleep():
public class DelayThread implements Runnable {
private final int DELAY;
public DelayThread(int delay) {
this.DELAY = delay;
}
#Override
public void run() {
try {
Thread.sleep(DELAY);
System.out.println("task executed");
} catch (InterruptedException ex) {
System.out.println("interrupted");
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new DelayThread(2000));
thread1.start();
Thread.sleep(500);
Thread thread2 = new Thread(new DelayThread(2000));
thread2.start();
System.out.println("All threads are started");
}
}
My goal is to schedule a recurrent job that happens on a non-even rate. I am going to migrate from first snippet to the second:
1st:
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
if (msg.what == MSG1) {
//recurrent job here
long nextTime = nextTime();
sendMessageAtTime(obtainMessage(MSG1), nextTime);
}
}
}
};
2nd:
ScheduledExecutorService mExecutor;
while (true){
mExecutor.schedule(new Callable() {
public Object call() throws Exception {
long startTime = SystemClock.uptimeMillis();
//recurrent job here
delay = nextTime() - startTime ;
return true;
}
}, delay, TimeUnit.MILLISECONDS);
}
My questions are:
1- is it true in the first snippet that the thread, to which the mHandler is referring, is free between jobs to do other tasks or handle other messages?
2- However in the second snippet, Thread is always busy doing the loop. right?
3- How can I rewrite the second code so that I won't loose thread activity between jobs (in delays)?
Any help is highly appreciated
Your second code won't work as expected. After the first task has been scheduled and is waiting to be executed, the while loop continues to schedule more tasks, all of them with the same delay. So you'll end up having thousands, probably millions of tasks. And of course, because the main thread is running an infinite loop without any wait, it is busy all the time. This is probably not what you want.
You should better use a simliar approach than the handler uses above:
final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.schedule(() -> {
// do work
// reschedule
executor.schedule(this, nextTime() - System.currentTimeMillis());
}, delay, TimeUnit.MILLISECONDS);
(Of course you should also check that the delay you specify when rescheduling is not negative).
Update: If you need to process the result of each execution individually, another approach similar to your second code example is possibly what you want. It schedules the task executions insisde a loop and hands over the result to a Consumer, as soon as it is available. (Note the future.get() inside the loop which causes the looping thread to pause until the task is done).
public static <T> void schedule(ScheduledExecutorService scheduler,
Schedule schedule, Callable<T> task, Consumer<? super T> consumer)
throws InterruptedException, ExecutionException {
while (true) {
if (Thread.interrupted()) throw new InterruptedException();
long delay = schedule.nextTime() - System.currentTimeMillis();
if (delay < 0) continue; // skip this step
ScheduledFuture<? extends T> future = scheduler.schedule(task,
delay, schedule.getUnit());
consumer.accept(future.get());
}
}
Also note the interruption check, so that other threads can stop execution by interrupting the looping thread. This simplifies the usage of this method inside another task in case you want to run it on a background thread too.
Schedule could be a functional interface that provides access to the scheduling information:
#FunctionalInterface
public interface Schedule {
long nextTime();
default TimeUnit getUnit() { return TimeUnit.MILLISECONDS; }
}
Btw.: The android.os.Handler is a very nice way to do what you want in android. So you should only migrate to ScheduledExecutorService if you really need its features (e.g. getting a Future result).
public class RecurrentJobThatHappensOnANonEvenRate {
/**
* Consider you have your job defined as below
*/
abstract class TheJob implements Runnable {
#Override
public void run() {
long startTime = System.currentTimeMillis();
doRecurrentJob();
schedule(nextTime() - startTime);
}
void doRecurrentJob() {
// Do the job
}
long nextTime() {
// calculate next execution time
long randomDelay = Math.round(5000 + Math.random() * 5000);
return System.currentTimeMillis() + randomDelay;
}
public abstract void schedule(long delay);
};
/**
* Example using `ScheduledExecutorService`.
*/
public void exampleWithScheduledExecutorService() {
TheJob theJob = new TheJob() {
private final ScheduledExecutorService executor =
Executors.newScheduledThreadPool(1);
#Override
public void schedule(long delay) {
executor.schedule(this, delay, TimeUnit.MILLISECONDS);
}
};
theJob.schedule(1500);
}
/**
* Example with `Handler` and using already existing `Thread` with
* `Looper` (most probably the main looper).
*/
public void exampleWithHandlerAndMainLooper() {
TheJob theJob = new TheJob() {
private final Handler handler =
// new Handler();
// or if you are not in the main thread:
new Handler(Looper.getMainLooper());
#Override
public void schedule(long delay) {
handler.postDelayed(this, delay);
}
};
theJob.schedule(1500);
}
/**
* Example with `Handler` and `HandlerThread` (a convenience thread
* class with looper).
*/
public void exampleWithHandlerAndHandlerThreadsLooper() {
TheJob theJob = new TheJob() {
private final HandlerThread handlerThread;
private final Handler handler;
private final long killThreadAt;
{
handlerThread = new HandlerThread("myThread");
// handler thread must be quit when you no longer use it.
// see nextTime() method below.
killThreadAt = System.currentTimeMillis() + 30000;
// alternatively you can set it to be a daemon thread.
// handlerThread.setDaemon(true);
handlerThread.start();
handler = new Handler(handlerThread.getLooper());
}
#Override
public void schedule(long delay) {
handler.postDelayed(this, delay);
}
#Override
long nextTime() {
long nextTime = super.nextTime();
if(nextTime() > killThreadAt) {
handlerThread.quit();
}
return nextTime;
}
};
theJob.schedule(1500);
}
}
I had some similar issues .. I was trying to schedule different jobs at different rates and I found using the Quartz Scheduler library to handle all my scheduling problems a real relieve :)
For your problem: firing a job at a non-even rate, you could easily implement a TriggerListener and on completion reschedule the same job at nextTime()
The Quartz Scheduler easily integrates with Spring, Maven and has handles for all kind of scenarios like misfired jobs or thread exceptions.
Simple example (from the docs)
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler();
// define the job and tie it to our HelloJob class
JobDetail job = newJob(HelloJob.class)
.withIdentity("job1", "group1")
.build();
// compute a time that is on the next round minute
int minutesInterval = nextTime();
// Trigger the job to run on the next round minute and repeat it forever
Trigger trigger = newTrigger()
.withIdentity("trigger1", "group1")
.withSchedule(
simpleSchedule()
.withIntervalInMinutes(minutesInterval)
.repeatForever()
)
.build();
// Tell quartz to schedule the job using our trigger
sched.scheduleJob(job, trigger);
sched.start();
I'm trying to use a timer to schedule a recurring event in an application. However, I want to be able to adjust the period at which the event fires in real time (according to the users input).
For example:
public class HelperTimer extends TimerTask
{
private Timer timer;
//Default of 15 second between updates
private int secondsToDelay = 15;
public void setPeriod(int seconds)
{
this.secondsToDelay = seconds;
long delay = 1000; // 1 second
long period = 1000*secondsToDelay; // seconds
if (timer != null)
{
timer.cancel();
}
System.out.println(timer);
timer = new Timer();
System.out.println(timer);
timer.schedule(this, delay, period);
}
public int getPeriod()
{
return this.secondsToDelay;
}
}
I then start a new instance of this class and call its set period function. However, when I do that, I get an Illegal state exception. You can see the System.out.println(timer); in there because I'm checking, and yep sure enough, they are two different timers... so why am I getting an IllegalStateException when I try to run a schedule call on a brand new Timer instance!?!?!?!
java.util.Timer#c55e36
java.util.Timer#9664a1
Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Task already scheduled or cancelled
at java.util.Timer.sched(Unknown Source)
at java.util.Timer.schedule(Unknown Source)
at HelperTimer.setPeriod(HelperTimer.java:38)
You can't reuse a TimerTask as you're doing here.
Relevant porition of Timer:
private void sched(TimerTask task, long time, long period) {
if (time < 0)
throw new IllegalArgumentException("Illegal execution time.");
synchronized(queue) {
if (!thread.newTasksMayBeScheduled)
throw new IllegalStateException("Timer already cancelled.");
synchronized(task.lock) {
//Right here's your problem.
// state is package-private, declared in TimerTask
if (task.state != TimerTask.VIRGIN)
throw new IllegalStateException(
"Task already scheduled or cancelled");
task.nextExecutionTime = time;
task.period = period;
task.state = TimerTask.SCHEDULED;
}
queue.add(task);
if (queue.getMin() == task)
queue.notify();
}
}
You'll need to refactor your code so that you create a new TimerTask, rather than re-using one.
It seems odd to me to have a TimerTask with its own Timer inside it. Bad design. I'd totally separate the two and have the TimerTask implementation be handed off to a Timer, and put all that logic about fiddling with the period inside another class that provides an interface for doing so. Let that class instantiate the Timer and TimerTask and send them off to do their work.
You can use ScheduledExecutorService, which allows you to schedule the same task multiple times without using scheduleAtFixedRate. Here's a quick example:
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
Runnable timerTask = new Runnable() {
#Override
public void run() {
// Do something
System.out.println("Task run!");
// Schedule again
executorService.schedule(this, 15, TimeUnit.SECONDS);
}
};
// Schedule
executorService.schedule(timerTask, 15, TimeUnit.SECONDS);
In this exmaple, "Executed...." will be printed after 4 seconds of delay. After that, it will be printed continuously every 3 seconds:
import java.util.*;
class TimeSetting {
public static void main(String[] args) {
Timer t = new Timer();
TimerTask time = new TimerTask() {
public void run() {
System.out.println("Executed......");
}
};
t.scheduleAtFixedRate(time, 4000, 3000);
/*
* The task will be started after 4 secs and
* for every 3 seconds the task will be continuously
* executed.....
*/
}
}
I'd like to have a java.utils.Timer with a resettable time in java.I need to set a once off event to occur in X seconds. If nothing happens in between the time the timer was created and X seconds, then the event occurs as normal.
If, however, before X seconds has elapsed, I decide that the event should occur after Y seconds instead, then I want to be able to tell the timer to reset its time so that the event occurs in Y seconds.
E.g. the timer should be able to do something like:
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).
I don't see a way to do this using the utils timer, as if you call cancel() you cannot schedule it again.
The only way I've come close to replicating this behavior is by using javax.swing.Timer and involves stopping the origional timer, and creating a new one. i.e.:
timer.stop();
timer = new Timer(8000, ActionListener);
timer.start();
Is there an easier way??
According to the Timer documentation, in Java 1.5 onwards, you should prefer the ScheduledThreadPoolExecutor instead. (You may like to create this executor using Executors.newSingleThreadScheduledExecutor() for ease of use; it creates something much like a Timer.)
The cool thing is, when you schedule a task (by calling schedule()), it returns a ScheduledFuture object. You can use this to cancel the scheduled task. You're then free to submit a new task with a different triggering time.
ETA: The Timer documentation linked to doesn't say anything about ScheduledThreadPoolExecutor, however the OpenJDK version had this to say:
Java 5.0 introduced the java.util.concurrent package and
one of the concurrency utilities therein is the
ScheduledThreadPoolExecutor which is a thread pool for repeatedly
executing tasks at a given rate or delay. It is effectively a more
versatile replacement for the Timer/TimerTask
combination, as it allows multiple service threads, accepts various
time units, and doesn't require subclassing TimerTask (just
implement Runnable). Configuring
ScheduledThreadPoolExecutor with one thread makes it equivalent to
Timer.
If your Timer is only ever going to have one task to execute then I would suggest subclassing it:
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);
}
}
You will need to work on the code to add checks for mis-use, but it should achieve what you want. The ScheduledThreadPoolExecutor does not seem to have built in support for rescheduling existing tasks either, but a similar approach should work there as well.
The whole Code snippet goes like this .... I hope it will be help full
{
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);
}
}
}
Do you need to schedule a recurring task? In that case I recommend you consider using Quartz.
I don't think it's possible to do it with Timer/TimerTask, but depending on what exactly you want to achieve you might be happy with using java.util.concurrent.ScheduledThreadPoolExecutor.
this is what I'm trying out. I have a class that polls a database every 60 seconds using a TimerTask.
in my main class, I keep the instance of the Timer, and an instance of my local subclass of TimerTask. the main class has a method to set the polling interval (say going from 60 to 30). in it, i cancel my TimerTask (which is my subclass, where I overwrote the cancel() method to do some cleanup, but that shouldn't matter) and then make it null. i recreate a new instance of it, and schedule the new instance at the new interval in the existing Timer.
since the Timer itself isn't canceled, the thread it was using stays active (and so would any other TimerTasks inside it), and the old TimerTask is replaced with a new one, which happens to be the same, but VIRGIN (since the old one would have been executed or scheduled, it is no longer VIRGIN, as required for scheduling).
when i want to shutdown the entire timer, i cancel and null the TimerTask (same as i did when changing the timing, again, for cleaning up resources in my subclass of TimerTask), and then i cancel and null the Timer itself.
Here is the example for Resetable Timer . Try to change it for your convinence...
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));
}
}
This example prints the current date and time for every 5 seconds...But if you give any input in console the timer will be delayed to perform the given input task...
I made an own timer class for a similar purpose; feel free to use it:
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);
}
}