I have scheduled a method to run at a certain date in the future; however, there are certain events that may or may not happen before that date that would mean I want to run the method earlier than the specified date; how can I do this? I currently have:
Timer timer = new Timer();
TimerTask task = new TaskToRunOnExpriation();
timer.schedule(task, myCalendarObject.getTime());
I will have many of these TimerTask's running in my application, stop specific instances of them if a certain even happens?
EDIT
I will only ever want to cancel a single Timer for a given event, is there a way of managing the identities for the Timers such that I can easily find and stop it?
If you have thousands of them you should use a ScheduledExecutorService which will pool threads rather than a Timer which will use one thread per timer.
The ScheduledFutures returned by the executor service when you schedule a task also have a cancel method to cancel the underlying tasks: future.cancel(true);.
As for cancelling the right task, you could store the futures in a Map<String, Future> so you can access them by name or id for example.
In C# I would say use delegates, but that is not an option in Java. I would work off this idea:
class Timers
{
Timer timer1;
Timer timer2;
ArrayList<Timer> timerList;
public Timers()
{
// schedule the timers
}
// cancel timers related to an event
public void eventA()
{
timer1.cancel();
timer2.cancel();
}
public void eventB()
{
for(Timer t : timerList)
t.cancel();
}
}
Use this schedule method.
public void schedule(TimerTask task,Date firstTime,long period)
task--This is the task to be scheduled.
firstTime--This is the first time at which task is to be executed.
period--This is the time in milliseconds between successive task executions
I use Timer in android to update a progress bar.Here is some of my code, hoping it can help you:
Timer timer ;
#Override
protected void onCreate(Bundle savedInstanceState) {
//....
timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
updateLogoBarHandler.sendEmptyMessage(0);
Log.e("SplashActivity","updating the logo progress bar...");
}}, 0, 50);
//.....
}
//here do the timer.cancel();
private Handler updateLogoBarHandler = new Handler() {
public void handleMessage(Message msg) {
if(logobarClipe.getLevel() < 10000){
logobarClipe.setLevel(logobarClipe.getLevel() + 50);
}else{
timer.cancel();
}
super.handleMessage(msg);
}
};
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'm trying to test the use of time in Java to manipulate code. So let's say I have a app with an egg. The egg won't hatch until 60 seconds have passed in the application, what method or class would I use to do this?
The Timer class should do what you are after:
A facility for threads to schedule tasks for future execution in a background thread. Tasks
may be scheduled for one-time execution, or for repeated execution at
regular intervals.
You can take a look at a simple example available here.
You can use timer in a way like this
Timer timer = new Timer();
If you want your code to run multiple times:
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// Your logic here
// Your logic will run every 60 second
System.out.println("egg hatched");
}
}, 0, 60000);
If you want it to run only one time
timer.schedule(new TimerTask() {
#Override
public void run() {
// Your logic here
System.out.println("egg hatched");
}
}, 60000);
You can read more about class timer in java here
The easiest old-fashioned single thread approach is
Thread.sleep(60*1000);
System.out.println("egg hatched");
And there is no guaranty that it print exactly after minute
System.currentTimeMillis() returns the current time of the system in milliseconds to your. So you need to create a Thread checking for the current time in a while loop an react to it.
Try run it it a separate scheduled thread;
ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1);
Runnable hatcher = new Runnable() {
#Override
public void run() {
egg.hatch();
}
};
scheduler.schedule(hatcher, 60, TimeUnit.SECONDS);
i have a problem with a method that i want to be called every x seconds.
In the constructor of my class I have something like that :
public class MyClass extends RelativeLayout{
public MyClass(Context context) {
// bla bla….
mTimer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
callMyMethodPeriodically();
}
}, 0, 20000); // every 20 seconds..
}
}
When I press the back button, the callMyMethodPeriodically method still is being called..
Even if i exit the application!
Do you have any ideas?? How can i stop this periodically calling?
Thank you
Try to override the onPause method on your Activity, the onPause will be called when the system is about to start resuming a previous activity. This is typically used to commit unsaved changes to persistent data, stop animations and other things that may be consuming CPU, etc. Implementations of this method must be very quick because the next activity will not be resumed until this method returns.
#Override
protected void onPause() {
super.onPause();
mTimer.cancel();
mTimer.purge();
mTimer = null;
}
You can try timer.canel() method or you can do it by this way
private Runnable runnable = new Runnable()
{
public void run()
{
//
// Do the stuff
//
handler.postDelayed(this, 1000);
}
};
and to stop:
handler.removeCallbacks(runnable);
or this way
you could look into using a ScheduledThreadPoolExecutor instead of a Timer.
Usage is pretty straight forward. You create an instance of an executor:
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor( 1 );
And then when you want to add a task you call:
executor.scheduleAtFixedRate( myRunnable, delay, interval, unit );
Where myRunnable is your task (which implements the Runnable-interface), delay is how long before the task should be executed the first time, interval is time between the execution of the task after first execution. delay and interval are meassured based on the unit parameter, which can be TimeUnit.* (where * is SECONDS, MINUTES, MILLISECONDS etc.).
Then to stop the execution you call:
executor.shutdownNow();
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.
For my MIDI player, I wanted to print 10 times in a second to get an accuracy of the timing but, the program consume quite a large amount of memory, how do I fix the code?
public void tick(int seconds) {
timer = new Timer();
timer.schedule(new tickcount(), seconds * 100);
}
class tickcount extends TimerTask {
public void run() {
if(sequencer != null) {
System.out.println("sec"+sequencer.getMicrosecondPosition()/1000000);
timer = null;
tick(1);
} else {
timer.cancel();
}
}
}
I don't really see how this code could be causing any kind of large memory consumption, unless it has to do with the incredible rate at which it'll be creating new threads.
At any rate, you should use a ScheduledExecutorService... Timer is kind of outdated (though even using it, you shouldn't be creating a new Timer each time your task runs). If you want the code in your tickcount task to run once every 0.1 seconds, you could do it like this:
private final ScheduledExecutorService scheduler =
Executors.newSingleThreadScheduledExecutor();
private Future<?> timingTask;
public void tick(long milliseconds) {
timingTask = scheduler.scheduleAtFixedRate(new Runnable() {
public void run() {
System.out.println("sec"+sequencer.getMicrosecondPosition()/1000000);
}
}, 0, milliseconds, TimeUnit.MILLISECONDS);
}
Here, the tick method will start your timer running, calling the Runnable every milliseconds ms, starting immediately. It also assigns a Future<?> to a field... this allows you to call timingTask.cancel(true) to cancel the scheduled task from running prior to setting sequencer to null.
Other than creating Timer object every time in tick() method call use a global timer object instance and reuse it