Fairness issue in ScheduledExecutorService - java

The following example shows an issue in the ScheduledExecutorService. I am scheduling two tasks "1" and "2" running longer than the schedule interval. Task "2" submits another task to execute only once.
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class TestExecutorFairness {
public static void main(final String[] args) {
final int interval = 200;
final int sleeptime = 600;
final ScheduledExecutorService executor = Executors
.newSingleThreadScheduledExecutor();
// schedule task 1
executor.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(sleeptime);
} catch (final InterruptedException e) {
e.printStackTrace();
}
System.out.println("1");
}
}, interval, interval, TimeUnit.MILLISECONDS);
// schedule task 2
executor.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(sleeptime);
} catch (final InterruptedException e) {
e.printStackTrace();
}
System.out.println("2");
// submit task 3
executor.submit(new Runnable() {
#Override
public void run() {
System.out.println("3");
}
});
}
}, interval, interval, TimeUnit.MILLISECONDS);
}
}
The output I would expect is something like
1
2
1
2
3
But it is not executed that way. The task "3" is delayed very long but I need it to be executed ASAP.
Is there any way to change this behaviour to more fairness? Or has someone a better solution?

Interesting. It seems counterintuitive, because the JvaDoc of ScheduledExecutorService explicitly mentions
Commands submitted using the Executor.execute(java.lang.Runnable) and ExecutorService submit methods are scheduled with a requested delay of zero
So one could assume that it should be feasible to submit commands like this. But in this case, there are some peculiarities. I can't point my finger at THE exact reason for this behavior, but it's obviously related to
The tasks taking longer than the schedule interval
The new task being submitted from an executed task
The fact that the ScheduledExecutorService internally uses a DelayedWorkQueue
Most importantly: That you are using a single-threaded ScheduledExecutorService
A considerable problem might also be that this is filling up the work queue and will sooner or later lead to an OutOfMemoryError. This can also be seen in this (slightly adjusted) example:
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class TestExecutorFairness {
public static void main(final String[] args) {
final int interval = 200;
final int sleeptime = 600;
final ScheduledExecutorService executor =
Executors.newScheduledThreadPool(1);
final long start = System.currentTimeMillis();
// schedule task 1
executor.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(sleeptime);
} catch (final InterruptedException e) {
e.printStackTrace();
}
System.out.println("1 at "+(System.currentTimeMillis()-start));
}
}, interval, interval, TimeUnit.MILLISECONDS);
// schedule task 2
executor.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(sleeptime);
} catch (final InterruptedException e) {
e.printStackTrace();
}
System.out.println("2 at "+(System.currentTimeMillis()-start));
System.out.println("Submitting 3 to "+executor);
// submit task 3
executor.submit(new Runnable() {
#Override
public void run() {
System.out.println("3 at "+(System.currentTimeMillis()-start));
}
});
}
}, interval, interval, TimeUnit.MILLISECONDS);
}
}
The number of "queued tasks" in the Executor constantly increases.
A solution in this case is rather simple: Instead of a
Executors.newScheduledThreadPool(1)
you can just create a
Executors.newScheduledThreadPool(3)
Of course, this changes the "timing behavior" in this example. I have to assume that the Thread.sleep() in this example was solely intended to simulate a complex computation that did not fit into this example code. But maybe just making sure that the number of threads is at least numberOfPeriodicTasks+1 can also be applied in your real application.

Related

Using ScheduledExecutorService, How to Start a Thread without waiting for other thread to complete at fixed interval?

I want to run a task at every particular interval of time regardless of completion of previous thread. And I've used ScheduledExecutorService with the schedule time at every one second. But the problem is, in my Runnable, If I make thread to sleep for 5 seconds, My ScheduledExecuterService also getting executed in every 5 seconds while it supposed to run each thread at 1 second.
It seems like it ScheduledExecuterService is waiting for previous thread to completion. But I want, The task to be triggered at every 1 second no matter what if job inside the task waits for longer time.
Here's is my code.
public class MyTask implements Runnable {
public void run() {
System.out.println("hi there at: "+ new java.util.Date());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
And here's my ScheduledExecutorService Code.
public class JavaScheduledExecutorServiceExample {
public static void main(String[] args) {
ScheduledExecutorService execService = Executors.newScheduledThreadPool(5);
execService.scheduleAtFixedRate(new MyTask(), 0, 1000, TimeUnit.MILLISECONDS);
}
}
Correct me If I'm doing something wrong. And If I'm wrong, is there any alternative to achieve the same? Providing Any best practices could be more helpful :)
"If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute." The behavior you are seeing is consistent with the javadocs
I believe this will perform the way you specified:
public class JavaScheduledExecutorServiceExample {
private static ScheduledExecutorService execService = null;
private static int timesAsleep = 0;
public static class MyTask implements Runnable {
public void run() {
System.out.println("hi there at: "+ new java.util.Date());
// schedule again
execService.schedule(new MyTask(), 1000, TimeUnit.MILLISECONDS);
try {
int i = timesAsleep;
timesAsleep++;
System.out.println("asleep " + i + "----------------------");
Thread.sleep(5000);
System.out.println("awoke " + i + "----------------------");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
execService = Executors.newScheduledThreadPool(5);
execService.schedule(new MyTask(), 1000, TimeUnit.MILLISECONDS);
}
}
Notice the use schedule() instead of scheduleAtFixedRate() on the ScheduledExecutorService instance. It also schedules the next task as soon as it starts the new task.

Exception handling with multiple futures from ScheduledExecutorService

I am using a ScheduledExecutorService to which I add both submit Runnables as well as scheduled Runnables (using scheduleWithFixedDelay).
The intention is to have very long running processes and thus non of my runnables have a defined lifetime. I basically want the main thread to only react to exceptions and interruptions.
The scheduled tasks are critical, e.g. generating heatbeats, and thus if any thread throw a runtimeexception I want to log the exception, abort all other threads and close the program.
How should I handle the exceptions? The ScheduledExecutorService swallows all the exceptions unless I run Future.get().
Looping through the futures, like below, does not work. If the first item in the futures list doesn't return any errors that will block the thread from listening on the other threads that might return error.
for (Future<?> future : futures) {
future.get();
}
One option would be looping through the futures asking if they are done, like below, but I don't really like this solution. I need to add a thread sleep and thus the response to an exception is delayed.
boolean allActive = true;
while (allActive) {
for (Future<?> future : futures) {
if (!future.isDone()) {
allActive = false;
break;
}
}
Thread.sleep(50);
}
What other options do I have? Or am I approaching the problem wrong?
Shouldn't I use a ScheduledExecutorService at all and implement the schedule myself in my own thread?
Example code, try change the order to the future list! I want the behavior you get if you add handle before handle2 but the order of the list shouldn't matter:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Test {
private static int i = 0;
public static void main(String[] args) throws Exception {
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
Future<?> handle = scheduler.scheduleWithFixedDelay(new Runnable() {
public void run() {
System.out.println("No exception!");
if (i > 2) {
System.out.println("Exception!");
throw new RuntimeException("foo");
}
i++;
}
}, 0, 500, TimeUnit.MILLISECONDS);
Future<?> handle2 = scheduler.scheduleWithFixedDelay(new Runnable() {
public void run() {
System.out.println("Running!");
}
}, 0, 500, TimeUnit.MILLISECONDS);
List<Future<?>> futures = new ArrayList<>();
futures.add(handle2);
futures.add(handle);
try {
for (Future<?> future : futures) {
future.get();
}
} catch (Exception e) {
scheduler.shutdownNow();
System.out.println(scheduler.awaitTermination(1, TimeUnit.SECONDS));
System.out.println("Shuwdown complete");
e.printStackTrace();
}
}
}
You can do it with a Listener or Observer-Like pattern:
interface IFutureListener{
void onException( Throwable t );
}
final IFutureListener errHandler = new IFutureListener(){
#override public void onException( Throwable t ){
// shutdown Service here
}
};
// ...
Future<?> handle = scheduler.scheduleWithFixedDelay(new Runnable() {
final IFutureListener callback = errHandler;
public void run() {
try{
System.out.println("No exception!");
if (i > 2) {
System.out.println("Exception!");
throw new RuntimeException("foo");
}
i++;
}
catch( Exception ex ){
callback.onException(ex);
}
}
}, 0, 500, TimeUnit.MILLISECONDS);
You still might need some tweaks to this, but this is the gist of it.
Guava's ListenableFuture as #dimo414 writes in comment will give you something similar. But if you do not want / are not allowed to use 3rd parties, this is a way you can implement it yourself.
Thanks to #efekctive: I also suggest logging exceptions. They should almost never just be swallowed silently except you know exactly what you are doing.

Java: How to make a new thread every second

I have a thread in Java that makes a web call and stores the information retrieved, but it only retrieves information for that particular instant. I'd like to run this thread every second for a certain period of time to get a better view of the data. How can I do this? I've looked at ScheduledExecutorService, and from what I can tell if the thread is still running when it's time to set up the next run, it waits until the first thread is complete, which isn't what I'm looking for.
You can do this by a double schedule. Use scheduleWithFixedDelay() to set off a job every second. This job starts the method which you really want to run. Here is some code based on Oracle's ScheduledExecutorService API.
The Thread.sleep() is there to simulate a long-running task.
class Beeper {
public static void main(String[] args) {
(new Beeper()).beep();
}
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
public void beep() {
final Runnable beeper = new Runnable() {
public void run() {
System.out.println("beep");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
final Runnable beeper2 = new Runnable() {
public void run() {
(new Thread(beeper)).start();
}
};
final ScheduledFuture<?> beeperHandle = scheduler.scheduleAtFixedRate(beeper2, 1, 1, SECONDS);
}
}
What you need is the scheduleAtFixedRate method: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html#scheduleAtFixedRate(java.lang.Runnable,%20long,%20long,%20java.util.concurrent.TimeUnit)
When the scheduler waits until the first thread is complete, it's because you're using scheduleWithFixedDelay.
However, if you absolutely want the threads run concurrently, you should try this:
pool.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
pool.submit(myJob);
}
}, 1, 1, TimeUnit.SECONDS);
I advise to always use a pool.
What about this?
public static void main (String [] args) throws InterruptedException{
ExecutorService executorService =
Executors.newFixedThreadPool(10);
while (true){
executorService.submit(new Runnable() {
#Override
public void run() {
// do your work here..
System.out.println("Executed!");
}});
Thread.sleep(1000);
}
}

How do I execute a method at a particular time in java?

Is there any way to write a program in java, so that its main method schedule (or at a 10-15 min interval) another method to executes it at a particular interval?
You can use Job scheduler for this. i.e.
Quartz Job Scheduler.
Refer this Quartz API
Or
You can use ScheduledExecutorService Java Interface
Refer this Documentation
I think you are looking for the Time class.
See Timer Class API
You can use this class like:
You want to perform a Method every 600 miliseconds. You write:
ActionListener taskPerformer = new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
//Do your stuff
}
};
Timer t = new Timer(600, taskPerfomer);
t.start;
There are more options. This example will be executed once but it can be executed in an interval.
I hope it helps.
Use Scheduled Thread pool executor:
Schedual your worker thread to execute at every 10 Seconds
scheduledThreadPool.schedule(worker, 10, TimeUnit.SECONDS);
1) Class WorkerThread .java
public class WorkerThread implements Runnable{
private String command;
public WorkerThread(String s){
this.command=s;
}
#Override
public void run() {
System.out.println(Thread.currentThread().getName()+" Start. Time = "+new Date());
processCommand();
System.out.println(Thread.currentThread().getName()+" End. Time = "+new Date());
}
private void processCommand() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public String toString(){
return this.command;
}
}
2) Class ScheduledThreadPool .java
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledThreadPool {
public static void main(String[] args) throws InterruptedException {
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
//schedule to run after sometime
System.out.println("Current Time = "+new Date());
for(int i=0; i<3; i++){
Thread.sleep(1000);
WorkerThread worker = new WorkerThread("do heavy processing");
scheduledThreadPool.schedule(worker, 10, TimeUnit.SECONDS);
}
//add some delay to let some threads spawn by scheduler
Thread.sleep(30000);
scheduledThreadPool.shutdown();
while(!scheduledThreadPool.isTerminated()){
//wait for all tasks to finish
}
System.out.println("Finished all threads");
}
}
If your task is not so big, you can use Thread.sleep() method(example 10 iteration with 10 minutes delay):
public static void main(String[] args) throws InterruptedException {
methodOne();
for (int i = 0; i < 10; i++) {
Thread.sleep(600000);
methodTwo();
}
}

Is there a solution for an ExecutorService that time limits each submitted Callable

Here is what I have... I have a list of tasks that will each be submitted on its own ExecutorService. I want each task to have a time limit of x MS after it has started execution. I have seen solutions like the one posted at Time Limit on Individual Threads but this puts a time limit starting on when the task was submitted.
I thought one solution would an extension to the accepted solution to Time Limit on Individual Threads. This would wrap the Callable in another Callable that would put the cancel task on the scheduled executor once it has started. This would involve a mapping of the Callable to the Future in an non-trivial manner so I thought I would post to see if anyone knows of an existing solution (code re-use being a wonderful thing and all).
Thanks.
As an FYI, the solution posted at Time Limit on Individual Threads is the following. Again this cancels from submit time, not start time:
ExecutorService service = Executors.newFixedThreadPool(N);
ScheduledExecutorService canceller = Executors.newSingleThreadScheduledExecutor();
public <T> Future<T> executeTask(Callable<T> c, long timeoutMS){
final Future<T> future = service.submit(c);
canceller.schedule(new Callable<Void>(){
public Void call(){
future.cancel(true);
return null;
}
}, timeoutMS, TimeUnit.MILLI_SECONDS);
return future;
}
Have a look if this works for you.
Sorry if the code is messy, but it is just to demonstrate the concept: pass back the future to the task, let the task start its own timer - the timer will start when the task start.
The following code adds 10 tasks, each takes 2 seconds to execute but the timeout is in 1 second.
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class CancellableTaskDemo {
public static void main(final String[] args) {
new CancellableTaskDemo();
}
final ExecutorService ex = Executors.newFixedThreadPool(3);
public CancellableTaskDemo() {
for (int i = 0; i < 10; i++) {
final int c = i;
submitTask(new Callable<Object>() {
#Override
public Object call() throws Exception {
final long t = System.currentTimeMillis();
try {
Thread.sleep(2000);
System.out.println("Task " + c + " done in " + (System.currentTimeMillis() - t) + "ms");
} catch (final InterruptedException e) {
System.out.println("Task " + c + " aborted after " + (System.currentTimeMillis() - t) + "ms");
}
return null;
}
}, 1000);
}
ex.shutdown();
try {
ex.awaitTermination(100000, TimeUnit.MILLISECONDS);
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
private void submitTask(final Callable<Object> c, final int timeout) {
final TimedFutureTask tft = new TimedFutureTask(c, timeout);
final Future<?> ft = ex.submit(tft.getCallable());
tft.setFuture(ft);
}
static class TimedFutureTask {
final static ScheduledExecutorService canceller = Executors.newSingleThreadScheduledExecutor();
private Timer cancelTimer;
private Callable<Object> timedCallable;
private Future<?> f;
private int timeoutMS;
public TimedFutureTask(final Callable<Object> callable, final int timeoutMS) {
this.timeoutMS = timeoutMS;
timedCallable = (new Callable<Object>() {
#Override
public Object call() throws Exception {
cancelTimer = new Timer();
cancelTimer.schedule(new TimerTask() {
#Override
public void run() {
f.cancel(true);
}
}, timeoutMS);
final Object res = callable.call();
cancelTimer.cancel();
return res;
}
});
}
public Callable<Object> getCallable() {
return timedCallable;
}
public void setFuture(final Future<?> future) {
f = future;
}
}
}
I would use a ScheduleExecutorService.
final Future future = es.submit(myTask);
ses.schedule(new Runnable() {
public void run() {
future.cancel(true);
}
}, timeout, timeUnit);
You can do it manually but its too much of a code to do a simple task :(
public void run() {
long start = System.nanoTime();
long timeout = 60 * 1000;
do {
// Do work here
} while (TimeUnit.MICROSECONDS.convert(System.nanoTime() - start,
TimeUnit.MICROSECONDS)
- start > timeout);
}
You can start the timer as part of the task you submit, so it will start when the task is executed. just, in this case, you cannot use future.cancel but you can interrupt the thread.Depending on the tasks you submit terminating gracefully and in a timely fashion can be easy or not.

Categories