How to Timeout a Thread

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:

  1. Have a CountDownLatch be count down by each Worker, when finished.
  2. In the main execution thread await with timeout on said latch.
  3. When that call returns, you can check the Latches's count to see if there has been the timeout hit (if it is >0).
  4. a) count = 0, all tasks finished in time.
    b) if not, loop the Futures and check their isDone. You don't have to call shutdown on the ExecutorService.
  5. 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



Leave a reply



Submit