My CheckStatus (TimerTask) is not stopping when I call cancel() inside the run method. this.cancel() also does not work. What am I doing wrong?
import java.util.TimerTask;
class CheckStatus extends TimerTask {
int s = 3;
public void run() {
if (s > 0)
{
System.out.println("checking status");
s--;
}
else
{
System.out.println("cancel");
cancel();
}
}
}
Heres my driver
import java.util.*;
class Game {
static Timer timer;
static CheckStatus status;
public static void main(String[] args) throws InterruptedException {
CheckStatus status = new CheckStatus();
timer = new Timer();
timer.scheduleAtFixedRate(status, 0, 3000);
}
}
It works for me - using exactly the code you posted, I saw:
checking status
checking status
checking status
cancel
... and nothing else, showing that the TimerTask has been cancelled - it's never executing again.
Were you expecting the Timer itself to shut down when it didn't have any more work to do? It doesn't do that automatically. It's not clear what your bigger goal is, but one option to avoid this is to make the TimerTask also cancel the Timer - that will work, but it's not terribly nice in terms of design, and means that the TimerTask can't run nicely within a timer which contains other tasks.
you are calling the cancel method of the timer task but you should call the cancel method of the timer itself to get your expected behaviour.
Related
I am trying to build more or less a watchdog class. If a value hasn't changed for a certain time, the class should do something.
Therefore I want to utilize a standard timer, the idea is to set a timer, and reset it as soon as the watched value changes.
public class Watchdog {
public final Timer TIMER = new Timer(true);
public final long DELAY;
public Watchdog(long delay){
DELAY=delay;
valueChanged();
}
public void valueChanged(){
TIMER.cancel();
TIMER.purge();
TIMER.schedule(new TimerTask() {
#Override
public void run() {
Watchdog.this.alarm();
}
}, DELAY);
}
public void alarm(){
System.out.println("Watchdog barked");
}
}
Unfortunately I get an IllegalStateException every time I call TIMER.cancel(), as there is no timer set at the first call. What am I doing wrong? How to reset the timer, even if there is no timer set?
EDIT
Stacktrace
Exception in thread "main" java.lang.IllegalStateException: Timer already cancelled.
at java.util.Timer.sched(Timer.java:397)
at java.util.Timer.schedule(Timer.java:193)
at deleteme.Watchdog.valueChanged(Watchdog.java:28)
at deleteme.Watchdog.<init>(Watchdog.java:22)
at deleteme.Deleteme.main(Deleteme.java:19)
Java Result: 1
According to the Timer source code, the cancel method changes the value of an internal flag called newTasksMayBeScheduled to false.
public void cancel() {
synchronized(queue) {
thread.newTasksMayBeScheduled = false;
queue.clear();
queue.notify(); // In case queue was already empty.
}
}
The value of this flag is checked prior to scheduling a new task and it fires the exception you get as it is false.
if (!thread.newTasksMayBeScheduled)
throw new IllegalStateException("Timer already cancelled.");
I think that you should use the cancel method of the TimerTask instead of Timer.
For the sake of completeness of the answer, note that an alternative would be to use ScheduledThreadPoolExecutor.
I would like to know where is the problem in this class, I'm making a class that every n seconds make something, but it appear to do it only 1 time.
this is the class
import java.util.Timer;
import java.util.TimerTask;
public class Updater {
private Timer timer;
public Updater(int seconds){
timer = new Timer();
timer.schedule(new UpdaterTask(), seconds*1000);
}
class UpdaterTask extends TimerTask {
public void run() {
System.out.println(Math.random());
timer.cancel();
}
}
}
and this is the test
public class TestUpdater {
public static void main(String[] args){
new Updater(1);
}
}
i think that this test have to give me a random number every second but after the first second the process terminate.
Sorry for the bad english and thanks for any suggestion
schedule(task, delay) only execute the task once. schedule(task, delay, period) execute the task repeatedly with fixed delay.
timer.schedule(new UpdaterTask(), 0, seconds * 1000)
Remove cancel()
// timer.cancel();
You need to comment out, the timer.cancel() call. This is making the timer itself stop after the first execution of its timer task.
Then for repeated execution, you should call scheduleAtFixedRate method, with delay == 0, to start the task immediately, and period == x seconds, to run it every x seconds.
class Updater {
private Timer timer;
public Updater(int seconds){
timer = new Timer();
timer.scheduleAtFixedRate(new UpdaterTask(), 0, seconds*1000); // use scheduleAtFixedRate method
}
class UpdaterTask extends TimerTask {
public void run() {
System.out.println(Math.random());
//timer.cancel(); --> comment this line
}
}
}
When your main() thread terminates the application also terminates.
Just add Thread.sleep(10000) at the end of your code. It will then work for 10 seconds.
AND
Consult this answer for how to use the cancel method. I think you did not want to use it there.
AND
Change the scheduling type, use
timer.scheduleAtFixedRate(new UpdaterTask(), 0, seconds*1000);
I am trying to schedule a repeating timer in GWT, it will run every one milli second, poll for a certain event, if it is found satisfactory, do something and cancel the timer.
I tried doing this:
final Timer t = new Timer() {
public void run() {
if (..condition is true, exit) {
t.cancel();
doSomething();
}
}
}
t.scheduleRepeating(1);
However, I get an error message like the local variable t may not have been initialized. I am putting tis piece of code in the onSuccess clause of a RequestBuilder callback.. How do I achieve this?
You cannot access it while intializing itself.
change your code to
final Timer fgf = new Timer() {
#Override
public void run() {
cancel();
System.out.println();
}
};
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.
I'm calling this tasks:
TimerTask taskA = new ThreadA(this);
TimerTask taskB = new ThreadB(this);
tasks.add(taskA);
tasks.add(taskB);
timer.schedule(taskA, 10000);
timer.schedule(taskB, 5000);
And here are the two TimerTasks:
public class ThreadA extends TimerTask {
private Ghost ghost;
public GhostThread(Ghost ghost) {
this.ghost = ghost;
}
#Override
public void run() {
ghost.stopBeingDeadAndBeAwesomeAgain();
}
}
public class ThreadB extends TimerTask {
private Ghost ghost;
public WarnThread(Ghost ghost) {
this.ghost = ghost;
}
#Override
public void run() {
ghost.beDeadAgain();
}
}
As you can see, I just call a method after 5 resp. 10 seconds. From time to time I would like to pause the "countdown". This means i want that the time until the 5 seconds are passed isn't running anymore. And then in a later point in time, I would like to resume it.
How can I achieve that??
The simplest solution would be to simply make a copy of the TimerTask, cancel it to pause, purge if you want, and then reschedule it to resume.
// pause
long timeLeft = 5000 - (new Date().getTime() - taskB.scheduledExecutionTime());
ThreadB taskBpaused = taskB.clone();
taskB.cancel();
timer.purge();
taskB = taskBpaused;
// resume
timer.schedule(taskB, timeLeft, ...);
Important note: if the task hasn't run yet, then this won't work. Google's documentation states that if it hasn't run, scheduledExecutionTime() will return an undefined value, and I don't have the capability to test what exactly that means at the moment. Needless to say, if you aren't sure it's already run, you'll need some kind of conditional to make sure the value isn't undefined.