Currently using a ScheduledExecutorService to do a task every 45 minutes (for infinity).
executor.scheduleAtFixedRate(new Runnable() {
public void run() {
...
}, 10, 45 * 60, TimeUnit.SECONDS);
I was wondering if there was a proper way to know how long until the next iteration of the executor?
My un-proper way is to add a timer and resetting it every iterator of the executor but it feels very bad.
Related
I have an Scheduled Execution Service that executes a method every X seconds. Is it possible to have a method that can force the Scheduled Execution Service to skip the remaining time in the execution delay and call the method immediately. Or can I simply stop it and restart it immediately?
here is my code:
Runnable runnable = new Runnable() {
public void run() {
callTheFunction();
}
};
ScheduledExecutorService executor;
executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(Runnable, 0, 5, TimeUnit.SECONDS); // 0 sec delay | 5 sec repeat
public void restartTheExecutor() {
// code to restart it or skip the remaining time.
}
Here is my updated and working code, it contains a boolean in the parameters which must be set to false the first run.
public void restartExecutor(View v, boolean stopRequiered) {
if (stopRequiered) {
scheduled.cancel(true);
}
Runnable runnable = new Runnable() {
public void run() {
nextExpression();
}
};
ScheduledExecutorService executor;
executor = Executors.newScheduledThreadPool(1);
scheduled = executor.scheduleAtFixedRate(runnable, 0, 3, TimeUnit.SECONDS); // 0 sec delay | 5 sec repeat
}
It's not possible to enforce the scheduled function to run immediately with ScheduledExecutorService.
However, for the second question, the answer is yes. You can remove any scheduled function at any time and run it as you wish. You'll need the reference to the function separately though:
Runnable runnable = new Runnable() {
public void run() {
callTheFunction();
}
};
ScheduledExecutorService executor;
executor = Executors.newScheduledThreadPool(1);
Future<?> scheduled = executor.scheduleAtFixedRate(runnable, 0, 5, TimeUnit.SECONDS); // 0 sec delay | 5 sec repeat
// cancel and run immediately:
scheduled.cancel(true);
runnable.run();
Note, that cancel() will cancel not only the next (or current) run but also all the future runs. So you'll have to reschedule again:
// reassigned scheduled to next runs:
scheduled = executor.scheduleAtFixedRate(runnable, 5, 5, TimeUnit.SECONDS); // 5 sec delay | 5 sec repeat
Or simply do both the steps by running asynchronously with 0s delay and 5s repeat again:
scheduled.cancel(true);
scheduled = executor.scheduleAtFixedRate(runnable, 0, 5, TimeUnit.SECONDS); // 0 sec delay | 5 sec repeat
I'm trying to perform a task every 5 minute.
The task need to start from: xx:00, xx:05, xx:10, xx:15 and so on so if the time is xx:37 the task will start in xx:40.
I'm used the following code to do that:
Date d1 = new Date();
d1.setMinutes(d1.getMinutes() + 5 - d1.getMinutes()%5);
d1.setSeconds(0);
this.timer.schedule(new Send(), d1, TEN_MINUTES/2);
Send looks like that:
class Send extends TimerTask
{
public void run()
{
if(SomeCondition)
{
Timestamp ts1 = new Timestamp(new java.util.Date().getTime());
SendToDB(ts1);
}
}
}
So the result should be records that if you % the minutes the result would be 0.
But the records time I have is:
*05:35:00
*07:44:40
*07:54:40
*09:05:31
*09:50:00
As you can see the first task start perfectly but then something went wrong.
My guess is that the task calculateds the 5 minute jump after the previous task is finished so the task run time effects, but it's just a guess.
The time a task takes to execute will delay the schedule. From the docs for schedule:
If an execution is delayed for any reason (such as garbage collection or other background activity), subsequent executions will be delayed as well.
You will be better off using scheduleAtFixedRate.
Alternatively, you might try using a simple Thread with a loop to repeatedly perform the task. The last step in the loop can be to sleep the necessary time until you want to start the task again. Assuming that no one iteration of the loop takes five minutes, this will eliminate cumulative delays.
public void run() {
long start = System.currentTimeMillis();
while (shouldRun()) {
doTask();
long next = start + FIVE_MINUTES;
try {
Thread.sleep(next - System.currentTimeMillis());
start = next;
} catch (InterruptedException e) {
. . .
}
}
}
This will start each iteration at the next five-minute interval and will not accumulate delays due to the running time of doTask() or any system delays. I haven't looked at the sources, but I suspect that this is close to what's in Timer.scheduleAtFixedRate.
Why dont you use a Task scheduler or simply a sleep command in a loop which lets the thread sleep for 5 minutes then continue.
An alternative would be to use a Timer class
I would probably make use of ScheduleExecutorService.scheduleAtFixedRate which is a more modern approach than using a Timer and would allow for having multiple worker threads in case there are many tasks being scheduled.
I am trying to run a line of code every second by using System.currentTimeMillis();.
The code:
while(true){
long var = System.currentTimeMillis() / 1000;
double var2 = var %2;
if(var2 == 1.0){
//code to run
}//If():
}//While
The code which I want to run, runs multiple times because var2 is set to 1.0 multiple times due to the infinite whole loop. I just want to run the code line when var2 is first set to 1.0, and then every time again when var2 becomes 1.0 after 0.0.
If you want to busy wait for the seconds to change you can use the following.
long lastSec = 0;
while(true){
long sec = System.currentTimeMillis() / 1000;
if (sec != lastSec) {
//code to run
lastSec = sec;
}//If():
}//While
A more efficient approach is to sleep until the next second.
while(true) {
long millis = System.currentTimeMillis();
//code to run
Thread.sleep(1000 - millis % 1000);
}//While
An alternative is to use a ScheduledExecutorService
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
ses.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
// code to run
}
}, 0, 1, TimeUnit.SECONDS);
// when finished
ses.shutdown();
The advantage of this approach is that
you can have a number of tasks with different periods sharing the same thread.
you can have non-repeating delay or asynchronous tasks.
you can collect the results in another thread.
you can shutdown the thread pool with one command.
I'd use the java executor libraries. You can create a ScheduledPool that takes a runnable and can run for any time period you want. For example
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(new MyRunnable(), 0, 5, TimeUnit.SECONDS);
Will run the MyRunnable class every 5 seconds. MyRunnable must implement Runnable. The trouble with this is that it will (efficiently) create a new thread each time which may or may not be desirable.
You should have to use java.util.Timer and java.util.TimerTask class.
Using Thread.sleep(); would be perfect for your case.
while(true)
{
Thread.sleep(1000); // Waiting before run.
// Actual work goes here.
}
preferred way:
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
Then pass in Runnables like:
scheduler.scheduleWithFixedDelay(myRunnable, initDelay, delay, TimeUnit.MILLISECONDS);
I wouldn't use the Timer. Schedulers are built to handle problems that Timers can cause. Also, the Thread.sleep is good for a simple program that you're writing quickly for proof of concept type things but I wouldn't use it in the enterprise world.
I am using a while loop with a timer.
The thing is that the timer is not used in every loop.
It is used only the first time. After the first time the statements included inside the loop are executed without the delay that i have set.
How is this even possible since the timer is included inside the while loop.
Any solutions ?
int count = 1;
while (count <= 10) {
final Handler handler = new Handler();
Timer t = new Timer();
t.schedule(new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
// Stuff the while loop executes
}
});
}
}, 20000);
count++;
}
The TimerTask kicks off a new Thread and then the loop proceeds as normal.
The execution of the thread does not cause a delay to the execution of the code in your loop.
It's because you're queueing up 10 toasts all to execute in one hour. Each iteration of your loop takes only a fraction of a millisecond or maybe a tad bit more than that. To enqueue them properly, you could do 3600000 * count instead of 3600000 each time.
This is a terrible way to do it though. You should use AlarmManager for stuff like this.
You're scheduling 10 TimerTasks to execute after an hour, at the same time. So all 10 tasks are being executed after 1 hour, which makes it seem like 1 execute since all the Toast messages display at the same time. To schedule tasks at a fixed delay, with the first task starting in 1 hour, use this method:
Timer t = new Timer();
t.schedule(task, 3600000, 3600000);
This will execute until you call t.cancel().
I am using a while loop with a timer.
The thing is that the timer is not used in every loop.
It is used only the first time. After the first time the statements included inside the loop are executed without the delay that i have set.
How is this even possible since the timer is included inside the while loop.
Any solutions ?
int count = 1;
while (count <= 10) {
final Handler handler = new Handler();
Timer t = new Timer();
t.schedule(new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
// Stuff the while loop executes
}
});
}
}, 20000);
count++;
}
The TimerTask kicks off a new Thread and then the loop proceeds as normal.
The execution of the thread does not cause a delay to the execution of the code in your loop.
It's because you're queueing up 10 toasts all to execute in one hour. Each iteration of your loop takes only a fraction of a millisecond or maybe a tad bit more than that. To enqueue them properly, you could do 3600000 * count instead of 3600000 each time.
This is a terrible way to do it though. You should use AlarmManager for stuff like this.
You're scheduling 10 TimerTasks to execute after an hour, at the same time. So all 10 tasks are being executed after 1 hour, which makes it seem like 1 execute since all the Toast messages display at the same time. To schedule tasks at a fixed delay, with the first task starting in 1 hour, use this method:
Timer t = new Timer();
t.schedule(task, 3600000, 3600000);
This will execute until you call t.cancel().