This question already has answers here:
How to schedule a periodic task in Java?
(13 answers)
Closed 2 years ago.
how to call method multiple times within given time java
Ex: if I want to call method A() for 3 times within 120 seconds. these two values should be configurable
You should take a look at Timers in Java. Documentation of Java SE 8 of Timer can be found here.
Here's an example: You can adjust the delay, period to your own preference.
// Initialize the Timer, this is the actual function that will start a TimerTask
private static final Timer timer = new Timer();
// Initialize the TimerTask, this is like the recipe for the Timer
private static final TimerTask task = new TimerTask() {
// Create a variable to keep track how many times we have ran this code
private int count = 0;
// Function that will be ran in the TaskTimer
public void run() {
// Your Code goes here
// Add to the amount of times we have ran this code
count++;
// If the count has reached 3...
if( count == 3 ) {
// we cancel the task
task.cancel();
}
}
};
// Using the TimerTask
public static void main( String[] args ) {
// Set the delay (adjust this to your own needs)
long delay = 2000;
// Set the period (adjust this to your own needs)
long period = 5000;
// Schedule the TimerTask
timer.schedule(task, delay, period);
}
It's always a good idea to take a look if your dependency has it's own set of Timer and AsyncTimer, as sometimes it's more efficient to use there's.
Related
This question already has answers here:
Java execute method from within a loop every few seconds
(2 answers)
Closed 2 years ago.
I want to execute specific code located inside for loop every 5 seconds.
How can I do that?
In that case, a java.util.Timer would be a more fitting solution.
A timer allows you to execute a function every x milliseconds.
Though, you'll have to define and call the timer outside of the loop.
Alternatively, you can check out the link that #Filburt has suggested to see in which you can use the current time to execute a code within a loop every x seconds.
If you still want to go with the timer solution, here's how you set it:
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run () {
// code to execute
}
}, MILLISECONDS); // replace MILLISECONDS with the amount of milliseconds between each execution.
Note that the timer itself doesn't know when to stop. You can create a field in the anonymous class that counts each execution and cancels the timer when reaching a specific number:
Timer timer = new Timer();
timer.schedule(new TimerTask() {
int times = 0;
#Override
public void run () {
if (times == 5) { // replace 5 with the amount of times you want the code executed.
timer.cancel();
return;
}
// code to execute
times++;
}
}, MILLISECONDS);
I want to run java code for a certain duration ,say 16 hours! I have a java code that runs for approximately an hour.I want this to run repeatedly for 16 hours. So I have a parameter that is passed by the user through Jenkins ! I access this value using
System.getenv("Duration");
Now, I want to exit the execution after the specified time. So suppose the user selected 16, the script should run for 16 hours and then exit.
Accepting input from Jenkins user as shown in the image
I saw some other questions, but most of them were dealing with timers for either few seconds or few minutes. I need an efficient solution. Thanks :)
FYI - Environment - Jenkins+TestNG+Maven+Java
EDIT :
long start = System.currentTimeMillis();
long end = start + durationInHours*60*60*1000;
while (System.currentTimeMillis() < end)
{
//My code here runs for approx. 50 mins!
}
Now suppose the user chooses the value 3 hours, I want the while loop to exit after 3 hours. But this does not happen as it has not yet completed 3 hours when checking the while condition.So it enters the while condition even the 4th time(since time elapsed is 150 mins which is less than 180 mins) it ends after 3 hours ten mins.
How to make it exit the while loop as soon as 180 mins is reached ?
P.S - I could do the math first,( iterations =durationFromUser/codeDuration) and then run a for loop, but I don't want to do this as my script length may vary.
EDIT 2:
boolean alive = true;
Timer timer = new Timer();
#Test() //Annotation from TestNG
public void public void jenkinsEntryPoint()
{
String duration = System.getenv("Duration");
int durationInHours=Integer.parseInt(duration);
long end = System.currentTimeMillis() + durationInHours*60*60*1000;
TimerTask task = new TimerTask() {
public void run() {
alive = false;
};
timer.schedule(task, end);
while (alive) {
//My code here runs for approx. 50 mins!
function1();
}
}
void function1() {
function2();
}
private void function2() {
for(i=0;i<8;i++)
{
while(alive)
{
//long running code
sleep(1000);
//Some more code
sleep(2000);
//Some more code
//Suppose time elapses here, I want it to quit
//But its continuing to execute
.
.
.
.
}
}
}
The while condition will only be evaluated between script invocations (as you've seen). You will have to break out of your long running from inside of it.
I would typically use a Timer to set a "global" boolean that you would check from inside the loops in your long running code.
Something like this. Notice checks against 'alive' would have to be in all you long loops...
boolean alive = true;
Timer timer = new Timer();
public void jenkinsEntryPoint()
long end = System.currentTimeMillis() + durationInHours*60*60*1000;
TimerTask task = new TimerTask() {
public void run() {
alive = false;
};
timer.schedule(task, end);
while (alive) {
//My code here runs for approx. 50 mins!
yourLongRunningCode()
}
public void yourLongRunningCode() {
while (alive) {
doStuff();
}
}
I tried ScheduledThreadPoolExecutor and it worked!
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
exec.scheduleAtFixedRate(new Runnable() {
public void run() {
System.out.println("Time's Up According To ScheduledThreadPool");
alive = false;
}
}, durationInHours, 1, TimeUnit.HOURS);
This function will be executed after "durationInHours".
Thanks #TedBigham :)
What is the difference between these 2 methods of Timer class :
schedule(TimerTask task, long delay, long period)
and
scheduleAtFixedRate(TimerTask task, long delay, long period)
Documentation doesn't make the difference between them clear.
The documentation does explain the difference:
schedule:
In fixed-delay execution, each execution is scheduled relative to the actual execution time of the previous execution. If an execution is delayed for any reason (such as garbage collection or other background activity), subsequent executions will be delayed as well.
So, suppose the delay is 5 seconds, and each task takes 2 seconds, you would get
TTWWWTTWWWTTWWWTT
where T means 1 second for the task execution, and W means 1 second waiting.
But now suppose that a long GC (represented by a G) happens and delays the second task, the third one will start 5 seconds after the start of the second one, as if the long GC didn't happen:
TTWWWGGTTWWWTTWWWTT
The third task starts 5 seconds after the second one.
scheduleAtFixedRate:
In fixed-rate execution, each execution is scheduled relative to the scheduled execution time of the initial execution. If an execution is delayed for any reason (such as garbage collection or other background activity), two or more executions will occur in rapid succession to "catch up.".
So, with the same delay as above, and the same GC, you would get
TTWWWGGTTWTTWWWTT
The third task task starts 3 seconds instead of 5 after the second one, to catch up.
Thanks #Nizet's answer, I have written a sample code for some people who want to practice and learn.
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
public static void main(String args[]){
TimerTest.DelayTask task = new DelayTask();
Timer timer = new Timer();
/**
* Use schedule or scheduletAtFixedrate and check the printed result
*/
timer.schedule(task, 0, 5000);
//timer.scheduleAtFixedRate(task, 0, 5000);
}
public static boolean stop = false;
public static void delayOneSec(String status){
try{
System.out.print(status);
Thread.sleep(1000);
}catch(Exception e){
e.printStackTrace();
}
}
static class DelayTask extends TimerTask{
int count = 2;
#Override
public void run() {
// TODO Auto-generated method stub
stop = true;
for(int i = 0; i < count; i++){
TimerTest.delayOneSec("T");
}
if(count == 2){
count = 6;
}else{
count = 2;
}
stop = false;
new PrintW().start();
}
}
static class PrintW extends Thread{
#Override
public void run(){
while(!stop){
TimerTest.delayOneSec("W");
}
}
}
}
The task itself will repeat to take 2 seconds or 6 seconds. Let's see the result of each scenario.
When using timer.schedule(task, 0, 5000);, the output is TTWWWTTTTTTTTWWWTTTTTTTTWWWTTTTTTTT. As you can see, the timer follow the rules like below, wait till period time outs if task finishes in time, launch next task immediately if current task lasts more than period.
When using timer.scheduleAtFixedRate(task, 0, 5000);, the output is TTWWWTTTTTTTTWWTTTTTTTTWWTTTTTTTTWWTTTTTTTTWWTTTTTTTTWWTTTTTTTT. Things are a little different now. The javadoc
two or more executions will occur in rapid succession to "catch up."
takes effect here. As you can see, ignoring the first TTWWW, every two tasks will print TTTTTTTTWW and it lasts 10 seconds(two periods).
Let's dig into the source code of Timer.
public void schedule(TimerTask task, Date firstTime, long period) {
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, firstTime.getTime(), -period);
}
public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
if (delay < 0)
throw new IllegalArgumentException("Negative delay.");
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, System.currentTimeMillis()+delay, period);
}
As you can see, the period is transferred to negative value in schedule method. Let's see what's the difference when scheduling it.
The below code is in the mainloop of TimerThread,
currentTime = System.currentTimeMillis();
executionTime = task.nextExecutionTime;
if (taskFired = (executionTime<=currentTime)) {
if (task.period == 0) { // Non-repeating, remove
queue.removeMin();
task.state = TimerTask.EXECUTED;
} else { // Repeating task, reschedule
queue.rescheduleMin(
task.period<0 ? currentTime - task.period
: executionTime + task.period);
}
}
}
It's where magic happens, for schedule method, the next task execution time is based on the currentTime which is calculated right before the this task runs. That means, every task's execution time only be related with previous task starts time.
I need to create a java function that will only run for 30 minutes, and at the end of the 30 minutes it executes something. But it should also be able to self terminate before the given time if the right conditions are met. I don't want the function to be sleeping as it should be collecting data, so no sleeping threads.
Thanks
Use: Timer.schedule( TimerTask, long )
public void someFunctino() {
// set the timeout
// this will stop this function in 30 minutes
long in30Minutes = 30 * 60 * 1000;
Timer timer = new Timer();
timer.schedule( new TimerTask(){
public void run() {
if( conditionsAreMet() ) {
System.exit(0);
}
}
}, in30Minutes );
// do the work...
.... work for n time, it would be stoped in 30 minutes at most
... code code code
}
Get the start time with System.currentTimeMillis(), calculate the time when to stop and check the current time every now and then while you're collecting the data you want to collect. Another way would be to decouple the timer and the data collecting, so that each of them could run in their own threads.
For a more specific answer, it would be helpful if you would tell what data you are collecting and how you are collecting it.
Something like this will work:
long startTime = System.currentTimeMillis();
long maxDurationInMilliseconds = 30 * 60 * 1000;
while (System.currentTimeMillis() < startTime + maxDurationInMilliseconds) {
// carry on running - 30 minutes hasn't elapsed yet
if (someOtherConditionIsMet) {
// stop running early
break;
}
}
The modern java.util.concurrent way would be using ExecutorService. There are several invoke methods taking a timeout.
Here's a kickoff example:
public static void main(String args[]) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.invokeAll(Arrays.asList(new Task()), 30, TimeUnit.MINUTES);
executor.shutdown();
}
where Task look like this:
public class Task implements Callable<String> {
#Override
public String call() {
// Just a dummy long running task.
BigInteger i = new BigInteger("0");
for (long l = 0; l < Long.MAX_VALUE; l++) {
i.multiply(new BigInteger(String.valueOf(l)));
// You need to check this regularly..
if (Thread.interrupted()) {
System.out.println("Task interrupted!");
break; // ..and stop the task whenever Thread is interrupted.
}
}
return null; // Or whatever you'd like to use as return value.
}
}
See also:
Lesson: Concurrency
I have developed code in Java for generating ten random numbers from a range 0 to 99. The problem is I need to generate a random number for every 2 min. I am new to this area and need your views.
This example adds a random number to a blocking dequeue every two minutes. You can take the numbers from the queue when you need them. You can use java.util.Timer as a lightweight facility to schedule the number generation or you can use java.util.concurrent.ScheduledExecutorService for a more versatile solution if you need more sophistication in the future. By writing the numbers to a dequeue, you have a unified interface of retrieving numbers from both facilities.
First, we set up the blocking queue:
final BlockingDequeue<Integer> queue = new LinkedBlockingDequeue<Integer>();
Here is the setup with java.utilTimer:
TimerTask task = new TimerTask() {
public void run() {
queue.put(Math.round(Math.random() * 99));
// or use whatever method you chose to generate the number...
}
};
Timer timer = new Timer(true)Timer();
timer.schedule(task, 0, 120000);
This is the setup with java.util.concurrent.ScheduledExecutorService
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Runnable task = new Runnable() {
public void run() {
queue.put(Math.round(Math.random() * 99));
// or use whatever method you chose to generate the number...
}
};
scheduler.scheduleAtFixedRate(task, 0, 120, SECONDS);
Now, you can get a new random number from the queue every two minutes. The queue will block until a new number becomes available...
int numbers = 100;
for (int i = 0; i < numbers; i++) {
Inetger rand = queue.remove();
System.out.println("new random number: " + rand);
}
Once you are done, you can terminate the scheduler. If you used the Timer, just do
timer.cancel();
If you used ScheduledExecutorService you can do
scheduler.shutdown();
You have two requirements which are unrelated:
Generate random numbers
Perform the task every 2 minutes.
To do anything every 2 minutes you can use a ScheduledExecutorService.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.Timer;
public class TimerExample {
Random rand = new Random();
static int currRand;
TimerExample() {
currRand = rand.nextInt(99);
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
currRand = rand.nextInt(99);
}
};
Timer timer = new Timer(2000, actionListener);
timer.start();
}
public static void main(String args[]) throws InterruptedException {
TimerExample te = new TimerExample();
while( true ) {
Thread.currentThread().sleep(500);
System.out.println("current value:" + currRand );
}
}
}
EDIT: Of course you should set 2000 in new Timer(2000, actionListener); to 120 000 for two minutes.
You can schedule your program to be run once every two minutes using whatever scheduling features are available to you in your target environment (e.g., cron, at, Windows Scheduled Tasks, etc.).
Or you can use the Thread#sleep method to suspend your application for 2,000ms and run your code in a loop:
while (loopCondition) {
/* ...generate random number... */
// Suspend execution for 2 minutes
Thread.currentThread().sleep(1000 * 60 * 2);
}
(That's just example code, you'll need to handle the InterruptedException and such.)
I'm not entirely sure I understand the problem. If you wish to generate a different random number every two minutes, simply call your rnd function every two minutes.
This could be as simple as something like (pseudo-code):
n = rnd()
repeat until finished:
use n for something
sleep for two minutes
n = rnd()
If you want to keep using the same random number for two minutes and generate a new one:
time t = 0
int n = 0
def sort_of_rnd():
if now() - t > two minutes:
n = rnd()
t = now()
return n
which will continue to return the same number for a two minute period.