I want to run repeated task 3 times only from a foreground service.
I tried to use ScheduledExecutorService
ScheduledExecutorService scheduler = Executors
.newScheduledThreadPool(1);
counter = 0;
scheduler.scheduleWithFixedDelay(new Runnable() {
public void run() {
if (counter<3) {
counter++;
System.out.println("Do something useful");
}
else {
scheduler.shutdownNow()
}
}
}
}, 2, 2, TimeUnit.SECONDS);
But im not sure if it's the right way to go with.
This repeated task will run only 3 times and will stop after that.
AlarmManager is another option but sounds to me like an overkill for this short period task.
Any advice would be helpful!
Related
This question is for a college assignment.
I want to run a block of code every n*2 seconds (e.g. wait 1 second and run and wait 2 seconds and run and wait 4 seconds and run, etc) up to 5 times.
I currently have something like this.
int timer = 1000;
int tryCounter = 0;
while( !condition() && counter < 5){
doTask();
Thread.sleep(timer);
timer *= 2;
counter++;
}
Although this works, my grade benefits from not using Thread.sleep(). I figured out using a ScheduledThreadPoolExecutor with a fixed rate would be one way to go but I cannot get it to work due to the fact that the interval is not actually fixed.
This is for a theoretical Distributed System with high concurrency capabilities so what matters is the high scalability.
I could get away with Thread.sleep() if there was really no benefit or a viable way of doing this by writing it on my report. So does anyone have any insight on this?
It is possible to schedule tasks with ScheduledExecutorService combined with some logic. The .schedule argument lets you specify a time unit to use. You can declare a variable that can handle the increment you are trying to do.
int timer = 1000;
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
Runnable runnable = new Runnable() {
public void run()
{
//Move your code you want to implement here
}
};
//Increment your variable
while(!condition()) {
for(int i = 0; i < 5; i++) {
service.schedule(runnable, timer, TimeUnit.SECOND);
timer *= 2;
}
}
Moving your code execution within the runnable block and then scheduling it within a for loop where the timer is incremented should accomplish the effect you are going for. Hope that helps!
So I have a repeating TimerTask that runs every x number of seconds (I say x as it can be changed by the user)
I also need to add a UI feature as "time until next execution" in seconds. I could do something where I store an AtomicInteger which I increment every second, and then do some other checking of that integer for if I want to actually 'run' the task. However I'm ideally looking for a simpler way (for example, if I run the task every second but the actual code should be running every 566ms, it won't work properly). I've taken a look at TimerTask#scheduledExecutionTime, but that returns the last time it's run. Is there an easier way to do this? Thanks
you could use ScheduledThreadPoolExecutor.scheduleAtFixedRate
here is simple example
public static void main(String[] args) throws InterruptedException {
ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(10);
ScheduledFuture<?> task = scheduledThreadPoolExecutor.scheduleAtFixedRate(() -> {
System.out.println("task");
}, 1, 1, TimeUnit.SECONDS);
scheduledThreadPoolExecutor.scheduleAtFixedRate(() -> {
System.out.println("until " + task.getDelay(TimeUnit.MILLISECONDS));
}, 500, 700, TimeUnit.MILLISECONDS);
Thread.sleep(10000);
scheduledThreadPoolExecutor.shutdownNow();
}
I want to Schedule a job to run at multiple of 2 seconds, which is 2,4,8,16,32 seconds. Second fire should happen after two seconds of completion of first fire, Third fire should happen after 4 seconds of completion of second fire and so on. The next fire is based on status we get from previous fire, based on which it will be decided whether we need to trigger next fire or not.
Can somebody tell me how can I use quartz scheduler to achieve this?
If I use SimpleTrigger.withIntervalInSeconds(2) it runs a job after every 2 seconds where as I want time interval should be increased with multiple of 2 in every firing.
Perhaps you could forget trying to set up a single trigger, but use multiple triggers. My Java is not good in this area, so this is in pseudocode:
delay = 2
repeat
TriggerOnceAfter(delay)
delay <- delay * 2
WaitUntilTriggered()
until (finished)
I am not sure how to implement the WaitUntilTriggered() method; you my need to add a signalling flag to the triggered code for WaitUntilTriggered() to look at.
That will give delays of 2, 4, 8, ...
This is a simplified implementation that will invoke a Runnable at the requested schedule:
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class Tasker {
private int numberOfRuns; //how many times job executed
private int timeBetweenRuns;//seconds
Tasker(int numberOfRuns){
this.numberOfRuns = numberOfRuns;
timeBetweenRuns = 2;
execute();
}
private void execute() {
for (int counter = 0; counter < numberOfRuns ; counter++) {
CountDownLatch latch = new CountDownLatch(1);
Job job = new Job(latch, timeBetweenRuns);
job.run();
try {
latch.await();
TimeUnit.SECONDS.sleep(timeBetweenRuns);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
timeBetweenRuns *=2;
}
}
public static void main(String[] args){
new Tasker(5);
}
}
class Job implements Runnable {
private int seconds;
private CountDownLatch latch ;
Job(CountDownLatch latch , int seconds){
this.latch = latch;
this.seconds = seconds;
}
#Override
public void run() {
System.out.println("Job runs "+ seconds +" after previous one");
latch.countDown();
}
}
I am writing a minigame for Minecraft and have a problem with the schedule. I don't know how to stop the schedule. Please tell me how I can stop running this loop / Timer / Schedule:
public void WarteTimer() {
count = Bukkit.getScheduler().scheduleSyncRepeatingTask(
(Plugin) this,
new Runnable() {
#Override
public void run() {
if (countdown > 0) {
Bukkit.broadcastMessage("ยง6Countdown : " +countdown);
countdown--;
} else {
Game();
//Bukkit.getScheduler().cancelTask(count);
//countdown = 5;
}
}
},
0L,
20L);
}
To stop a scheduler in bukkit you have to get the id for the scheduler and call the Bukkit scheduler cancel method.
I see you have already set count equal to the scheduler. I am assuming count is an integer.
To stop a scheduler simply put:
Bukkit.getScheduler().cancelTask(taskID);
In your case you will use :
Bukkit.getScheduler().cancelTask(count);
You can run this line where ever and it will stop your scheduler.
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 :)