I want to delay doing something, along the lines of setting a countdown timer that will "do a thing" after a certain amount of time.
I want the rest of my program to keep running while I wait, so I tried making my own Thread that contained a one-minute delay:
public class Scratch {
private static boolean outOfTime = false;
public static void main(String[] args) {
Thread countdown = new Thread() {
#Override
public void run() {
try {
// wait a while
System.out.println("Starting one-minute countdown now...");
Thread.sleep(60 * 1000);
// do the thing
outOfTime = true;
System.out.println("Out of time!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
countdown.start();
while (!outOfTime) {
try {
Thread.sleep(1000);
System.out.println("do other stuff here");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
While this worked, more-or-less, it seemed like there should be a better way of doing this.
After some searching, I found a bunch of questions like these but they don't really address what I'm trying to do:
How do I schedule a task to run at periodic intervals?
How i can run my TimerTask everyday 2 PM
How to run certain task every day at a particular time using ScheduledExecutorService?
Java execute task with a number of retries and a timeout
I don't need anything this complicated; I just want to do a single thing after a certain amount of time while letting the rest of the program still run.
How should I go about scheduling a one-time task to "do a thing"?
While the java.util.Timer used to be a good way to schedule future tasks, it is now preferable1 to instead use the classes in the java.util.concurrent package.
There is a ScheduledExecutorService that is designed specifically to run a command after a delay (or to execute them periodically, but that's not relevant to this question).
It has a schedule(Runnable, long, TimeUnit) method that
Creates and executes a one-shot action that becomes enabled after the given delay.
Using a ScheduledExecutorService you could re-write your program like this:
import java.util.concurrent.*;
public class Scratch {
private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
public static void main(String[] args) {
System.out.println("Starting one-minute countdown now...");
ScheduledFuture<?> countdown = scheduler.schedule(new Runnable() {
#Override
public void run() {
// do the thing
System.out.println("Out of time!");
}}, 1, TimeUnit.MINUTES);
while (!countdown.isDone()) {
try {
Thread.sleep(1000);
System.out.println("do other stuff here");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
scheduler.shutdown();
}
}
One of the nice things you get by doing things this way is the ScheduledFuture<?> object you get back from calling schedule().
This allows you to get rid of the extra boolean variable, and just check directly whether the job has run.
You can also cancel the scheduled task if you don't want to wait anymore by calling its cancel() method.
1See Java Timer vs ExecutorService? for reasons to avoid using a Timer in favor of an ExecutorService.
Thanks it worked for me. I used scheduler to schedule a task at a batchinterval calculated at runtime.
manualTriggerBatchJob.setSchedulingProperties(pblId, batchInterval);
ScheduledExecutorService scheduledExecutorService =
Executors.newScheduledThreadPool(5);
#SuppressWarnings("unchecked")
ScheduledFuture scheduledFuture =
scheduledExecutorService.schedule(manualTriggerBatchJob,
batchIntervalInMin,TimeUnit.MILLISECONDS);
Related
I am trying to use ScheduledExecutorService in an interval of 5 seconds with initial delay of 5 seconds till a condition is satisfied. Below is my code block
if (true) {
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
Runnable runnable = new Runnable() {
public void run() {
try {
//API calls which gives boolean true/false
if (true) {
executorService.shutdown();
}
} catch (Exception ex) {
System.out.println("Excepton in shutting down executorService: " + ex);
}
}
};
executorService.scheduleAtFixedRate(runnable, 5, 5, TimeUnit.SECONDS);
System.out.println("Executor ended");
}
//Other lines of code which should get executed after ScheduledExecutorService is done executing
//Call to API etc.
I want my other lines and api call code to execute after ScheduledExecutorService is done executing (Basically stop further program execution apart from ScheduledExecutorService) but at the moment it's not happening. At present while ScheduledExecutorService is waiting to be executed my down api call code executes. Also, i am not able to use any variable declared globally to be used inside ScheduledExecutorService. How to handle this? Thanks.
I'm querying an API to create a report and want to load that report 5 minutes later. I want to use a ScheduledExecutorService for that. As I don't want the Executor to block my thread, I'm creating a new thread for that, but am unsure if this is the correct way of doing this. Here's my code:
Thread thread = new Thread() {
public void run() {
log.info("Starting...");
new RequestReport().runScheduledTask(requestId);
}
};
thread.start();
private void runScheduledTask(String requestId) {
log.info("Starting five-minute countdown now...");
ScheduledFuture<?> countdown = scheduler.schedule(() -> {
try {
new GetReportList().run(requestId);
} catch (Exception e) {
e.printStackTrace();
}
}, 5, TimeUnit.MINUTES);
try {
countdown.get();
} catch (InterruptedException | ExecutionException e) {
log.info("catched Exception");
e.printStackTrace();
}
scheduler.shutdown();
}
Is there a better way to run a function 5 minutes after another? Is the way I'm doing this good? What should I change?
BTW, I'm using spring - is there something that could make that better?
ScheduledExecutorService is a good choice, but you use it incorrectly:
First of all, you don't need to create a Thread just to schedule a task from it. It adds nothing to the functionality, only wastes resources.
Second, after calling shutdown() your scheduler will no longer accept tasks, which is bad if you need to generate more than one report.
Third, since your code does nothing after the task completion, you don't need to call get() at all.
So, the only code you need is:
scheduler.schedule(() -> {
try {
new GetReportList().run(requestId);
} catch (Exception e) {
e.printStackTrace();
}
}, 5, TimeUnit.MINUTES);
It will schedule a task and release your thread immediately. The task will be executed five minutes later in a separate thread that is managed by scheduler.
If you need some control on the scheduled tasks (check their states, cancel them etc.), you can obtain Future from schedule() and save it somewhere, but based on the code from your question, you don't need it.
If you'd like to be more 'correct' about the code, you could separate the RequestReport into it's own class implementing the Runnable interface, and pass along an instance of said class to the Thread's constructor
I have written a piece of code . How can I get that code to run for certain duration repeatedly, say for 10 second?
The ExecutorService seems to provide methods which execute tasks until they are either completed or else a timeout occurs (such as the invokeAll).
You can give a try to Quartz Job Scheduler
Quartz is a richly featured, open source job scheduling library that
can be integrated within virtually any Java application - from the
smallest stand-alone application to the largest e-commerce system.
Quartz can be used to create simple or complex schedules for executing
tens, hundreds, or even tens-of-thousands of jobs; jobs whose tasks
are defined as standard Java components that may execute virtually
anything you may program them to do. The Quartz Scheduler includes
many enterprise-class features, such as support for JTA transactions
and clustering.
If you are familiar with Cron in Linux , this will be a cakewalk for you .
Use a worker and start it in a thread, wait in the main thread for the specific time and stop the worker after this.
MyRunnable task = new MyRunnable();
Thread worker = new Thread(task);
// Start the thread, never call method run() direct
worker.start();
Thread.sleep(10*1000); //sleep 10s
if (worker.isAlive()) {
task.stopPlease(); //this method you have to implement
}
Not too sure why people downvoted the question. Be sure to in the future provide some sample code. Your answer however is simple here. Create a new thread to watch the wait. In simple code:
public class RunningClass {
public static void runThis(){
TimerThread tt = new TimerThread();
tt.timeToWait = 10000;
new Thread(tt).start();
while (!TimerThread.isTimeOver){
\\Code to execute for time period
}
}
class TimerThread implements Runnable {
int timeToWait = 0;
boolean isTimeOver = false;
#override
public void run(){
Thread.sleep(timeToWait);
}
}
The code above can be put in the same class file. Change the 10000 to whatever time you require it to run for.
You could use other options, but it would require you to have knowledge on workers and tasks.
not sure what was the exact requirement, but
if your req was to cancel only a long running task
you could use ExecutorService & Future (in jdk 5) as follows.
ExecutorService fxdThrdPl = Executors.newFixedThreadPool(2);
// actual task .. which just prints hi but after 100 mins
Callable<String> longRunningTask = new Callable<String>() {
#Override
public String call() throws Exception {
try{
TimeUnit.MINUTES.sleep(100); // long running task .......
}catch(InterruptedException ie){
System.out.println("Thread interrupted");
return "";
}
return "hii"; // result after the long running task
}
};
Future<String> taskResult = fxdThrdPl.submit(longRunningTask); // submitting the task
try {
String output = taskResult.get(***10**strong text**, TimeUnit.SECONDS***);
System.out.println(output);
} catch (InterruptedException e) {
} catch (ExecutionException e) {
} catch (TimeoutException e) {
***taskResult.cancel(true);***
}
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 have this piece of code:
Timeout s = new Timeout();
Timer timer = new Timer();
timer.schedule(s, 1000L); // fires after 1 second
How can I launch the following piece of code as a thread by itself? Would I need to pass the timer and Timeout to a Runnable and then start it? What happens if the thread's Run() ends before the timer is fired?
I am thinking of doing this instead:
ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
Timeout s = new Timeout(); // Timeout is a runnable
ses.schedule(s, 10, TimeUnit.SECONDS);
but how do I exit the thread after the timeout? I run out of thread after a while
Thanks
I'm not exactly sure what you're asking, but I'll give it a shot.
How can I launch the following piece of code as a thread by itself?
In short...
Timeout.java
public class Timeout extends TimerTask {
boolean isDone = false;
#Override
public void run() {
// TODO something
synchronized(this) {
isDone=true;
this.notifyAll();
}
}
public synchronized void join() throws InterruptedException {
while(!this.isDone)
this.wait();
}
}
TimeoutRunner.java
public class TimerRunner implements Runnable {
#Override
public void run() {
Timeout timeout = new Timeout();
Timer timer = new Timer();
timer.schedule(timeout, 1000L);
try {
timeout.join();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
timer.cancel();
}
}
}
Run the TimeoutRunner using:
new Thread(new TimeoutRunner()).start();
The join method will block the thread until the timeout task has completed execution. At that time you can close the Timer. This is, however, a lot of thread creation, and IMO bad programming.
When you create a Timer instance, a thread is created to execute the Timeout#run() method. The timer has it's own run method that blocks until your task is ready for execution. After the given timeout period elapses, the timer unblocks and executes your timeout.
Your TimeoutRunner thread will block until the timeout operation completes. Only then can this thread die.
The Timer class is very limited. You need to create a new instance for every task. In my option, the ScheduledExecutorService is a better option. Keep the ScheduledExecutorService open for as long as you plan on executing tasks. If you need something like a scheduled cached thread pool, feel free to use this class from one of my open-source projects (Scheduler). This works great with a cached thread pool.