ScheduledExecutorService will execute irrespective of previous task completion status - java

I am using ScheduledExecutorService where at times task may run for 3 hours to complete pollMergeFiles.searchForFileAndExecute() method and some times it may take less than 2 minutes to complete.
My only question is if scheduler.scheduleAtFixedRate will end up executing every 10 minutes with a delay of 5 minutes or it will wait until previous task running to be completed and only then start new task?
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
...
PollMergeFiles pollMergeFiles = new PollMergeFiles();
final Runnable service = new Runnable() {
public void run() {
try {
if (counter <= 256) {
pollMergeFiles.searchForFileAndExecute();
} else if (counter > 256) {
logger.info(
"Shutdown the scheduler service since all counters were processed");
scheduler.shutdown();
}
} catch (Exception e) {
logger.error("Exception found", e);
}
}
};
scheduler.scheduleAtFixedRate(service, 5, 10, TimeUnit.Minutes);

You can check the Java doc https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html .
scheduleAtFixedRate(Runnable command, long initialDelay, long period,
TimeUnit unit) Creates and executes a periodic action that becomes
enabled first after the given initial delay, and subsequently with the
given period; that is executions will commence after initialDelay then
initialDelay+period, then initialDelay + 2 * period, and so on.
So scheduleAtFixedRate() won't wait for last task to finish. It will be executed at predefined interval (period field).
scheduleWithFixedDelay(Runnable command, long initialDelay, long
delay, TimeUnit unit) Creates and executes a periodic action that
becomes enabled first after the given initial delay, and subsequently
with the given delay between the termination of one execution and the
commencement of the next.
But scheduleWithFixedDelay() method can wait for a predefined time (delay field) after the last task is executed.

Related

Can I skip the current execution delay or restart immediately an Scheduled Execution Service?

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

Run code every second by using System.currentTimeMillis()

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.

How do I print summary message after all threads (in a pool) complete? [duplicate]

This question already has answers here:
ExecutorService, how to wait for all tasks to finish
(16 answers)
Closed 5 years ago.
I have a command line application. It runs a loop say 100 times and in the loop schedules a task using a thread. I am using ExecutorService so there are 4 threads running at any time.
After the loop ends, I want to print a summary message. E.g. time taken to complete all 100 tasks. When I stepped through the code the debugger went straight to the summary part, but the other tasks are still running. I understand this is because each thread runs on its own. So how do I print messages only after all threads complete?
ExecutorService exec = Executors.newFixedThreadPool(4);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
Runnable requestHandler = new Runnable() {
#Override
public void run() {
try {
// call task function in here
} catch (Exception ex) {
}
}
};
exec.execute(requestHandler);
}
exec.shutdown();
long endTime = System.currentTimeMillis();
LOGGER.info("******************SUMMARY******************");
LOGGER.info("Time taken : " + ((endTime - startTime)/1000) + " seconds, "
+ ((endTime - startTime)/1000/60) + " minutes");
From the main-thread, you could create another thread that does everything from declaring exec to exec.shutdown();. After creating this thread, you put the main-thread to wait. At the end of the new thread's actions(after exec.shutdown();) you should notify it.
See http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html example copied for brevity
void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
Basically you need to wait until the ExecutorService isTerminated() method returns true. You can use awaitTermination() to that end.
The solution for you based on your code:
ExecutorService exec = Executors.newFixedThreadPool(4);
long start = System.currentTimeMillis();
//Your code
exec.shutdown();
while(true) {
if(exec.isTerminated()) {
long end = System.currentTimeMillis();
System.out.println("Time : " + (end - start));
break;
}
Check this out! It works!

restricting execution time sample of threads in java

I want to simulate a scheduler in java. I have three threads defined. Now I want to execute Thread 1 to be take 10% time, Thread 2 to take 30% and Thread 3 to take remaining 60% of time approximately.
All the three threads are continous monitoring tasks which will never end.
i.e. If I execute the program for 100 minutes, then Thread 1 executes for 10 mins, Thread 2 for 30 mins & Thread 3 for 60 minutes.
and also whenever threads are being shifted (i.e. another threading going into running state), I should print that "Thread x executed for Y seconds"
Can any one please provide some pointers on achieving the above simulation in java.
This link should be interresting.
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class MainThread
{
public static void main(String[] args)
{
int corePoolSize = 2;
ScheduledThreadPoolExecutor stpe = new ScheduledThreadPoolExecutor(corePoolSize);
/*
* This will execute the WorkerThread immediately
*/
stpe.execute(new WorkerThread("WorkerThread-Running-Immediately"));
/*
* This will execute the WorkerThread only once after 10 Seconds
*/
stpe.schedule(new WorkerThread("WorkerThread-Scheduled-After-10-seconds"), 10, TimeUnit.SECONDS);
/*
* This will execute the WorkerThread continuously for every 5 seconds with an initial delay of 10
* seconds for the first WorkerThread to start execution cycle. In this case, whether the first
* WorkerThread is completed or not, the second WorkerThread will start exactly after 5 seconds hence
* called schedule at fixed rate. This continues till 'n' threads are executed.
*/
stpe.scheduleAtFixedRate(new WorkerThread("WorkerThread-Running-At-Fixed-Rate"), 10, 5, TimeUnit.SECONDS);
/*
* This will execute the WorkerThread continuously with an initial delay of 10 seconds for the first
* WorkerThread to start execution cycle. Once the first thread execution completes then a delay of 5
* Seconds is introduced so that the next WorkerThread execution cycle starts. This continues till
* 'n' thread are executed. This is called schedule each thread with a fixed delay.
*/
stpe.scheduleWithFixedDelay(new WorkerThread("WorkerThread-Running-With-Fixed-Delay"), 10, 5, TimeUnit.SECONDS);
}
}
And a worker thread :
public class WorkerThread implements Runnable
{
private String threadName = null;
public WorkerThread(String threadName)
{
this.threadName = threadName;
}
public void run()
{
System.out.println(this.threadName + " started...");
try
{
Thread.sleep(5000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println(this.threadName + " ended...");
}
}

java- timing the execution of a block of code

hi
i want a block of code(certain lines of a function) that will run for a stipulated amount of time (say x milliseconds).Is is possible to do this in java?
1st approach:
long startTime = System.nanoTime();
while(System.nanoTime() - startTime < MAX_TIME_IN_NANOSECONDS){
// your code ...
}
2nd approach
Start your code in thread.
Sleep main thread for as long as you need.
Kill (stop, interrupt) your thread.
either use an exit condition based on current timestamp, or create a separate thread and kill it after a specified timeout.
Run your method in a separate thread, but passing it to an Executor. You can then use the Future to wait a certain period of time for the the thread to complete. If it doesn't complete, you will get a TimeoutException and you can then cancel the thread. Cancelling the thread causes the thread to be interrupted. So your code will have to periodically check the thread's interrupted status and exit if necessary.
For example:
ExecutorService exec = Executors.newSingleThreadExecutor();
Future<Integer> future = exec.submit(new Callable<Integer>(){
#Override
public Integer call() throws Exception {
//do some stuff
//periodically check if this thread has been interrupted
if (Thread.currentThread().isInterrupted()) {
return -1;
}
//do some more stuff
//check if interrupted
if (Thread.currentThread().isInterrupted()) {
return -1;
}
//... and so on
return 0;
}
});
exec.shutdown();
try {
//wait 5 seconds for the task to complete.
future.get(5000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
//the task did not complete in 5 seconds
e.printStackTrace();
System.out.println("CANCELLING");
//cancel it
future.cancel(true); //sends interrupt
}
You could use Calendar:
timeInMilis = Calendar.getInstance().getTimeInMillis();
while(Calendar.getInstance().getTimeInMilis() - timeInMilis < MAX_TIME_IN_MILIS){
// Execute block
}
Check the time using System.currentTimeMillis() and exit your loop after the time has passed.
long endTime = System.currentTimeMillis() + ClassName.EXECUTION_TIME_MS;
while (System.currentTimeMillis() < endTime) {
// do your stuff
}
If you need to sleep inside the thread for some reason, adjust your sleep time to end at the end time.
long timeLeft = endTime - System.currentTimeMillis();
if (sleepAmount > timeLeft)
sleepAmount = timeLeft;
Thread.sleep(sleepAmount);
If you're going to use the wait() and notify() method, then use the calculated timeLeft as the argument to wait() to ensure the maximum wait time. Once that wait time hits, the method will return and the loop will break.
long timeLeft = endTime - System.currentTimeMillis();
if (timeLeft > 0)
this.wait(timeLeft);
If you're running multiple steps inside the loop which can take a long time, you should add additional checks between steps, if you want the process to break between steps, to exit the loop if the designated time has passed. This is a design decision. When the timer expires, do you want the task to finish up the step it's working on and then exit? It's up to you how to code it based on the desired result.
long endTime = System.currentTimeMillis() + ClassName.EXECUTION_TIME_MS;
while (System.currentTimeMillis() < endTime) {
this.doFirstLongThing();
if (System.currentTimeMillis() >= endTime) break;
this.doSecondLongThing();
if (System.currentTimeMillis() >= endTime) break;
this.doThirdLongThing();
}

Categories