Java: Wait for TimerTask to complete before continuing execution - java

I'm having a bit of an annoying problem. Right now, I have a snippet of code that starts a thread, sets a timer within that thread, and then exits that thread and continues with its life. My intent here was for the program to wait for the TimerTask to complete before continuing with code flow. However, obviously, setting up a new TimerTask doesn't pause execution to wait for the timer to run down.
How do I set this up so that my code reaches the TimerTask, waits for the TimerTask to expire, and then continues? Should I even be using a Timer at all? I've looked everywhere for a solution, but I Can't seem to find one.
timer = new Timer();
Thread t = new Thread(new Runnable(){
boolean isRunning = true;
public void run() {
int delay = 1000;
int period = 1000;
interval = 10;
timerPanel.setText(interval.toString());
//Scheduling the below TimerTask doesn't wait
//for the TimerTask to finish before continuing
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
timerPanel.setText(setInterval().toString());
}
}, delay, period);
System.out.println("Thread done.");
}
});
t.start();
try {
t.join(); //doesn't work as I wanted
} catch (InterruptedException e) {
e.printStackTrace();
}
endTask();
Thanks in advance.
EDIT: Sorry for the confusion about the repeated task. I need the task to repeat because it's a countdown timer that pulses every second from 10 to 0. The function setInterval() eventually cancels the timer. Here's the relevant code:
private final Integer setInterval() {
if (interval == 1)
timer.cancel();
return --interval;
}

I believe a CountDownLatch will do what you want.
final CountDownLatch latch = new CountDownLatch(10);
int delay = 1000;
int period = 1000;
timerPanel.setText(Long.toString(latch.getCount()));
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
latch.countDown();
timerPanel.setText(Long.toString(latch.getCount()));
}
}, delay, period);
try {
latch.await();
}
catch (InterruptedException e) {
e.printStackTrace();
}
timer.cancel();

You should use Thread.sleep function instead of TimeTask to halt execution.
TimerTask is not meant to halt execution, its like a clock running in background. So for your requirement you should go for Thread.sleep.

Use a Semaphore. Initialize it before declaring the timer task, with 0 permits. In the timer task, use a try/finally block to release the semaphore. In the main thread, acquire the permit from the semaphore.
In your code, join works as specified since it waits for the thread to finish. And no, using a thread for this is not necessary. If you really want to block until a certain time, you don't need a Timer. Get the current time, compute the millis until the future time, and sleep().

Related

Java - How could I create a timer to run in the background of a program, while still allowing the user to interact? [duplicate]

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.

Creating a thread that will execute after delay

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");
}
}

Android Java Timer()

I'm using Timer() due to its accuracy but works in the same was as PostDelayed Handler. It's called only once. Here is the Timer code:
public void setWFT() {
WFT = new Timer();
WFT.schedule(new TimerTask() {
#Override
public void run() {
WFTTimerMethod();
}
}, 60000); // 60 seconds delay
}
private void WFTTimerMethod() {
this.runOnUiThread(Timer_Tick);
}
private Runnable Timer_Tick = new Runnable() {
public void run() {
// My commands here
}
};
This only calls run() once after 60 seconds once the Timer is started. Sometimes, I have to cancel the Timer to Update the delay (replace the "60000" value). To start the Timer again, I simply recreate the Timer by calling WFT() again with the new delay value.
Problem is, when I cancel the timer using:
WFT.cancel();
WFT.purge();
The Timer does not start. the run() doesn't execute when it's supposed to. So my question is do I use cancel() and purge() or just cancel()?
Thanks
From the Java API on purge():
Most programs will have no need to call this method. It is designed for use by the rare application that cancels a large number of tasks. Calling this method trades time for space: the runtime of the method may be proportional to n + c log n, where n is the number of tasks in the queue and c is the number of cancelled tasks.
So you only need to call cancel()
from cancel() documentation :
No more tasks may be scheduled on this Timer.

Implementing a timer in java

My situation is, I have two concurrent threads, one that cant start a timer and the other can stop the timer. The timer works in a way such that, once it has started it will count to 5 seconds and execute a function after, it will keep doing this until the timer is stopped by the other thread. How can this be implemented in Java. This is what I have, I feel it is the wrong way of doing it:
Note that sleep is a global volatile variable that the other two threads turn on and off.
void creatTime(final EventHandler handler)
{
Thread timer = new Thread()
{
public void run()
{
try
{
while(true)
{
while(sleep) Thread.sleep(1000);
//invoke function
}
}
catch(IOException e)
{
System.out.println(e);
}
}
};
timer.start();
}
}
You can create a TimerTask and schedule it to run every 5 seconds
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
// TODO Auto-generated method stub
//Invoke your function here
}
};
//Create a Timer and schedule it
Timer timer = new Timer();
timer.scheduleAtFixedRate(timerTask, 0, 5*1000);
//To terminate the Timer you can call its cancel method.
I agree with the TimerTask recommendation. In general, the more of your thread-related work you can pass on to the higher level features of java.util.concurrent etc. the better. For example, the original code does not deal with early wake-ups from sleep.
In addition, if the sleep variable remains after redesign, it needs to be marked volatile or accessed through synchronized get and set methods. There is a limited set of activities that ensure that writes done in one thread must become visible to reads done in another thread.

using Timer class - How can I make a scheduled Job started as scheduled even if the prior job isn't finished?

Without using Quartz, is there any option for Timer class or workaround to start scheduled jobs even if the previous job is not finished?
Here's sample code.
Job Scheduled for every 1 sec
public static void main(String[] args) {
Timer timer = new Timer();
Calendar date = Calendar.getInstance();
timer.scheduleAtFixedRate(new UnitTest(timer), date.getTime(), 1000);
}
Job Performed
Each job has 2 second delay
public void run() {
count++;
int a = count; // to see which job is started and ended.
System.out.println(this.now("HH:mm:ssSSS")+"- start "+count);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
System.out.println(this.now("HH:mm:ssSSS")+"- end "+a);
}
Result - if the previous job is not finished, then the next job is not started.
12:14:21946 - start 1
12:14:23965 - end 1
12:14:23965 - start 2
12:14:25966 - end 2
12:14:25967 - start 3
12:14:27968 - end 3
12:14:27968 - start 4
12:14:29969 - end 4
12:14:29970 - start 5
12:14:31970 - end 5
12:14:31971 - start 6
12:14:33972 - end 6
How can I add this option for Timer class?
Quartz - Concurrent Option from http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/scheduling.html
By default, Quartz Jobs are stateless, resulting in the possibility of jobs interfering with each other. If you specify two triggers for the same JobDetail, it might be possible that before the first job has finished, the second one will start. If JobDetail classes implement the Stateful interface, this won't happen. The second job will not start before the first one has finished. To make jobs resulting from the MethodInvokingJobDetailFactoryBean non-concurrent, set the concurrent flag to false.
EDITED SAMPLE CODE
public class TEST01 {
Timer timerTEST01 = new Timer();
public String[] start()
{
try
{
timerTEST01.scheduleAtFixedRate(new TimerTask() {
public void run() {
Runnable r = new Runnable() {
public void run() {
//DoWork
}
};
Thread t = new Thread(r);
t.start();
}
}, date.getTime(), 1000*60);
return new String[]{"true", "Good Job!"};
}
catch(Exception e){}
finally{}
}
}
Instead of running the code directly at the timer, when the timer calls your method, spawn a new thread (or use a thread poll) to execute your task:
public void run() {
Runnable r = new Runnable() {
public void run() {
count++;
int a = count; // to see which job is started and ended.
System.out.println(this.now("HH:mm:ssSSS")+"- start "+count);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
System.out.println(this.now("HH:mm:ssSSS")+"- end "+a);
}
};
Thread t = new Thread(r);
t.start();
}
This will guarantee that every single job executes at the given time even if the previous one hasn't executed.
Also, make sure your code works inside an anonymous inner class, that count++ probably isn't going to work.
TimerTask timertask=new TimerTask(
public void run(){
//code
}
);
Timer timer = new Timer();
//Use timer to execute and set time limits for execution

Categories

Resources