I have implmented a TimeoutTask using ExecutorService. In the below method I am submitting the TimeoutTask and if it is timed out in a given time, I cancel the task and shuts down the executor.
private boolean waitForProcessToBeCompleted(long timeOut) {
boolean result = false;
ExecutorService executor = Executors.newSingleThreadExecutor();
// Create a FutureTask which will be run
FutureTask<Boolean> futureTask = new FutureTask<Boolean>(new TimeoutTask());
executor.submit(futureTask); // Run the FutureTask
try {
result = futureTask.get(timeOut, TimeUnit.MILLISECONDS); // Check if FutureTask completed in the given time
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
futureTask.cancel(true);
result = true; // Return True only when timed out
} finally {
executor.shutdownNow(); // Stop the executor
}
return result;
}
It is running very well and I don't have any issue.
However, I would like to know whether this is the best code design. I was just wondering if it could have been better to use a Future returned by ExecutorService.submit() to get the return value of the Callable or to time out the TimeoutTask. e.g.
Future<?> futureTask = executor.submit(new TimeoutTask()); // Run the FutureTask
try {
result = futureTask.get(timeOut, TimeUnit.MILLISECONDS); // Check if FutureTask completed in the given time
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
futureTask.cancel(true);
result = true; // Return True only when timed out
} finally {
executor.shutdownNow(); // Stop the executor
}
return result;
I am using JDK7.
I would prefer using CountDownLatch:
List<List<String>> elements = MyPartition.partition(bigObjectList, size);
List<Future<?>> tasks = new ArrayList<Future<?>>();
ExecutorService executor = Executors.newSingleThreadExecutor();
CountDownLatch doneSignal = new CountDownLatch(10);
for(List<String> l: elements) {
ReadTask worker = new ReadTask(doneSignal, l);
tasks.add(executor.submit(worker));
}
long timeout = 10000;
doneSignal.await(timeout, TimeUnit.SECONDS);
boolean notFinished = false;
if(doneSignal.getCount() > 0) {
for(Future<?> fut : tasks) {
if(!fut.isDone()) {
System.out.println("Sub Thread " + fut + " has not finshed!");
fut.cancel(true);
notFinished = true;
}
}
}
If you look at the code of futureTask.cancel, you'll see that it just attempts to interrupt the thread which is executing the task. This interruption may work if the task regullary checks the interruption flag, explicitly or implicitly (via calling to sleep() or wait()). In Java, there is no other safe way to stop execution of a method.
So, you can implement the same functionality without creating each time a separate single-threaded executor. Instead, execute the TimerTask from within the waitForProcessToBeCompleted method. In order to be notified of timeout, submit a watching task to a SheduledExecutorService. The watching task should interrupt the thread which executes the TimerTask. If the task is completed before timeout, cancel the watching task.
This way you need a SheduledExecutorService, but it consumes very little processor cycles, and can be reused all over the application.
The invokeAll method on ExecutorService can be used to automatically cancel tasks that exceed the timeout. This lets you cancel tasks without shutting down the threadpool (which let's you re-use the same threadpool for other things if you choose).
private boolean waitForProcessToBeCompleted(long timeOut) {
ExecutorService executor = Executors.newSingleThreadExecutor();
List<FutureTask> tasks = new ArrayList<>();
tasks.add(new SomeFutureTaskThing()));
List<Future<Boolean>> results;
try {
results = executor.invokeAll(tasks, timeOut, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // Restore interrupt status.
return null;
} catch (ExecutionException e) {
throw new RuntimeException(e.getCause());
}
Future<Boolean> result = results.get(0);
try {
return result.get();
} catch (CancellationException e) {
System.err.println("Timed out");
return null;
}
}
Related
I want a task to run at scheduled interval and timeout if it does not complete in required time and continue further iteration.
I have gone through the following answers, but it doesn't address my problem..
How do you kill a Thread in Java?
ExecutorService that interrupts tasks after a timeout
Consider the following case
BasicThreadFactory collectionFactory = new BasicThreadFactory.Builder()
.namingPattern("CollectionExecutor-%d")
.build();
// thread pool size is set 2
// 1-for scheduler thread which runs task and tracks timeout
// 2-for task itself
ScheduledExecutorService collectionExecuter =
Executors.newScheduledThreadPool(2, collectionFactory);
// fires collection every minute and if it is in between execution during
// scheduled time then waits for completion and executes immediately
// after it
//my task:
Runnable runnable= new Runnable() {
#Override
public void run() {
try {
System.out.println("Executed started");
Thread.sleep(2000);
System.out.println("Executed after .get method call.");
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Thread.sleep(20000);
System.out.println("Executed even after .cancel method " +
"call (I want this to avoid this.)");
} catch (Exception e) {
e.printStackTrace();
}
}
};
Above task should run with an interval of 3 sec and stop if it takes more than 1 sec...Consider It is not possible to have complete task in single try catch block, now how could I stop the task to wait further in next sleep(20000) and continue with next iteration.
collectionExecuter.scheduleAtFixedRate(new Runnable() {//scheduler thread
#Override
public void run() {
try {
Future<?> future = collectionExecuter.submit(runnable);
try {
future.get(1, TimeUnit.SECONDS);
} catch (Exception e) {
future.cancel(true);
System.out.println("Collection thread did not " +
"completed in 1 Sec.Thread Interrupted");
}
} catch (Exception e) {
System.out.println("Unable to start Collection Thread");
}
}
}, 0, 3, TimeUnit.SECONDS);
}
I need to execute a Java method for at most X seconds.
In case the method's code does not terminate after X seconds, I need my execution to continue.
I tried to use the following code (using the ExecutorService class).
private void execLoop(){
ExecutorService executor = Executors.newSingleThreadExecutor();
int iteration;
for(iteration=0;iteration<10;iteration++) {
CallableTask ct = new CallableTask();
Future<String> future = executor.submit(ct);
try {
future.get(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
class CallableTask implements Callable {
#Override
public Object call() throws Exception {
Log.d("TIME","executed!");
int t=0;
boolean c = true;
while(c){
t+=0; // infinite loop: this method will never terminate
}
return null;
}
}
What I expect from this code is to print to logcat, every 5 seconds, the string "executed!" for 10 times.
However, the execution gets stuck in the infinite loop.
First, you never shut down your executor. Add the following line as the last statement in your execLoop() method:
executor.shutdownNow();
Then, since the shutdown is accomplished by interrupting your threads, you need to make sure that your CallableTask listens to interrupts. One way is to use Thread.sleep() instead of t+=0:
while(c){
Thread.sleep(500); // This will be interrupted when you call shutdownNow()
}
I want to run a thread for some fixed amount of time.
If it is not completed within that time, I want to either kill it, throw some exception, or handle it in some way. How can this be done?
You should use an ExecutorService:
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Integer> future = executor.submit(new Task());
try {
System.out.println("Started");
Integer retval = future.get(10, TimeUnit.SECONDS)); // you can choose your desired time here
System.out.println("Finished");
} catch (TimeoutException e) {
future.cancel(true);
System.out.println("Timeout happened");
// handle termination here
}
executor.shutdownNow();
And your Callable can look something like this:
class Task implements Callable<Integer> {
#Override
public String call() throws Exception {
// some code here
return 0;
}
}
The second thread in my code will throw a divide by 0 exception, but I will only catch it after the first thread finished. The first thread could run for days, so that means that I will only catch my exception after several days that it happened.
Can I solve this somehow without subclassing ThreadPoolExecutor and overriding afterExecute?
Here is my code:
ExecutorService executor = Executors.newCachedThreadPool();
Future<Integer> future = executor.submit(new MyTestC(4000));
Future<Integer> future2 = executor.submit(new MyTestC(0));
ArrayList<Future<Integer>> futures = new ArrayList<>();
futures.add(future); futures.add(future2);
for(Future<Integer> f: futures)
{
try {
int result = f.get();
System.out.println(result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
class MyTestC implements Callable<Integer> {
int sleep;
public MyTestC(int sleep)
{
this.sleep = sleep;
}
#Override
public Integer call() throws Exception {
if(sleep > 0)
Thread.sleep(sleep);
//If 0 will throw exception:
int tmp = 4/sleep;
return sleep;
}
}
you can use an ExecutorCompletionService to solve this problem. it will return Futures in the order they complete.
I'm using this code to divide up a few hundred tasks between different CPU cores.
final List<Throwable> errors = Collections.synchronizedList(Lists.<Throwable>newArrayList());
final ExecutorService pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
for (...) {
pool.execute(new Runnable() { #Override public void run() {
try {
// TASK HERE
} catch (Throwable e) {
errors.add(e);
}
}});
}
pool.shutdown();
try {
pool.awaitTermination(1000, TimeUnit.DAYS); // wait "indefinitely"
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (!errors.isEmpty()) throw Exceptions.wrap(errors.get(0)); // TODO multi-exception
It works, but it's not nice.
There is no version of awaitTermination without timeout, which is what I want.
I need to do my own error collecting.
What is the proper/common way to do this?
The point of a thread pool is to reuse threads. You should create it on application startup, outside of your code that creates tasks, and inject it. There is no need to shut down the pool after adding tasks. You do that when your application is shutting down.
To run a collection of tasks, use ExecutorService.invokeAll. To get the results afterwards, call get on each of the returned Futures. It will rethrow any exception that the task threw, so you can collect it afterwards.
You can use a future to do the error handling:
final List<Future> futures = new ArrayList<Future>();
for (int i = 0; i < 5; i++) {
futures.add(pool.submit(new Runnable() { #Override public void run() {
// TASK HERE
}}));
}
for (Future f : futures) {
try {
f.get();
} catch (ExecutionException e) {
//something bad happened in your runnable
}
}
//when you are done with the executor
pool.shutdown();
try {
pool.awaitTermination(1000, TimeUnit.DAYS); // wait "indefinitely"
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
I think you need to submit each Runnable, get a Future back, and then call get() on each Future.
When you call get(), you'll either get the result of the Runnable, or the exception that it encountered.