How to timeout a thread
Indeed rather use ExecutorService
instead of Timer
, here's an SSCCE:
package com.stackoverflow.q2275443;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class Test {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(new Task());
try {
System.out.println("Started..");
System.out.println(future.get(3, TimeUnit.SECONDS));
System.out.println("Finished!");
} catch (TimeoutException e) {
future.cancel(true);
System.out.println("Terminated!");
}
executor.shutdownNow();
}
}
class Task implements Callable<String> {
@Override
public String call() throws Exception {
Thread.sleep(4000); // Just to demo a long running task of 4 seconds.
return "Ready!";
}
}
Play a bit with the timeout
argument in Future#get()
method, e.g. increase it to 5 and you'll see that the thread finishes. You can intercept the timeout in the catch (TimeoutException e)
block.
Update: to clarify a conceptual misunderstanding, the sleep()
is not required. It is just used for SSCCE/demonstration purposes. Just do your long running task right there in place of sleep()
. Inside your long running task, you should be checking if the thread is not interrupted as follows:
while (!Thread.interrupted()) {
// Do your long running task here.
}
Java how to timeout a thread WITHOUT using future.get and without blocking parent thread
You can cancel long running task from a timer task:
import java.util.Timer;
import java.util.TimerTask;
Timer timer = new Timer();
Future<?> future = service.submit(new MyCallable());
TimerTask controlTask = new TimerTask(){
@Override
public void run() {
if (!future.isDone()) {
future.cancel(true);
}
}
};
long delay = 100;
timer.schedule(task, delay);
How can I implement a Runnable with timeout?
You are right, such approach with starting one more thread is not perfect. It would be hard to support such code.
I'd suggest to use a Thread Executor instead. Your code could look as follows:
Runnable receiveResponse = new Runnable() {
...
};
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> future = executor.submit(receiveResponse);
try {
Object result = future.get(5000, TimeUnit.MILLISECONDS);
System.out.println("Completed successfully");
} catch (InterruptedException e) {
...
} catch (ExecutionException e) {
...
} catch (TimeoutException e) {
System.out.println("Timed out. Cancelling the runnable...");
future.cancel(true);
}
executor.shutdown();
How to set thread timeout
In Java, you can use
CompletableFuture<Void> future = CompletableFuture.runAsync(processRunnable);
future.get(1000, TimeUnit.MILLISECONDS);
To future.get
function will throw a TimeOutException
when timeout (1 second in the example above) is reached and the timeout case can be handled in catch block.
Complete code will be something like this:
try {
CompletableFuture<Void> future = CompletableFuture.runAsync(processRunnable);
future.get(1000, TimeUnit.MILLISECONDS);
}
catch{
case texc : TimeoutException => println("Timeout is reached.")
case exc : Exception => println(exc.getmessage)
}
How set a timeout for my thread Handler method?
You can check for the timeout based on the number of trials. Also using thread and Thread.sleep
for running a periodic task is not a good practice.
To run a periodic task, you can post a Runnable
to a Handler
with some delay using postDelayed
method.
private Handler mHandler = new Handler();
private int mTrials = 0;
private Runnable mPeriodicTask = new Runnable() {
public void run() {
// Do the check
mTrials += 1;
if (mTrials == /* timeout number */) {
// timeout
} else {
mHandler.postDelayed(this, 2500);
}
}
}
To run the task:
mHandler.postDelayed(mPeriodicTask, 2500);
How to set timeout for thread in case of no response and terminate the thread?
You can use signal
and call its alarm
method. An exception (which you can handle) will be raised after the timeout time has passed. See an (incomplete) example below.
import signal
class TimeoutException (Exception):
pass
def signalHandler (signum, frame):
raise TimeoutException ()
timeout_duration = 5
signal.signal (signal.SIGALRM, signalHandler)
signal.alarm (timeout_duration)
try:
"""Do something that has a possibility of taking a lot of time
and exceed the timeout_duration"""
except TimeoutException as exc:
"Notify your program that the timeout_duration has passed"
finally:
#Clean out the alarm
signal.alarm (0)
You can read more about Python's signal
here https://docs.python.org/2/library/signal.html.
Java: Set timeout for threads in a ThreadPool
Have you seen this? ExecutorService.invokeAll
It should be exactly what you want: Invoke a bundle of workers and have them timeout if taking too long.
EDIT after comment - (new idea):
You can use a CountDownLatch to wait for the tasks to finish AND timeout via await(long timeout, TimeUnit unit)
!
You can then even do a shutdownNow and see which tasks have taken too long ...
EDIT 2:
To make it clearer:
- Have a CountDownLatch be count down by each Worker, when finished.
- In the main execution thread
await
with timeout on said latch. - When that call returns, you can check the Latches's count to see if there has been the timeout hit (if it is >0).
- a) count = 0, all tasks finished in time.
b) if not, loop the Futures and check theirisDone
. You don't have to call shutdown on the ExecutorService. - Call shutdown if you do not need the Executor any longer.
Note: Workers can finish in the meantime between the timeout and calling their Future's isDone().
Related Topics
How to Add Local .Jar File Dependency to Build.Gradle File
Maven: Add a Dependency to a Jar by Relative Path
How to Use Comparator in Java to Sort
Converting 'Arraylist≪String≫ to 'String[]' in Java
Which @Notnull Java Annotation Should I Use
Why Won't Eclipse Oxygen Start (For the First Time)
How to Programmatically Determine Operating System in Java
How to Enter Quotes in a Java String
Program Not Accessing Method Paintcomponent() of Extended Jpanel Class
Java Runtime.Getruntime(): Getting Output from Executing a Command Line Program
What's the Reason I Can't Create Generic Array Types in Java
What Is the Concept of Erasure in Generics in Java
How to Convert List≪Integer≫ to Int[] in Java
Should Java 8 Getters Return Optional Type