Killing Thread After Some Specified Time Limit in Java

Killing thread after some specified time limit in Java

Make use of ExecutorService to execute the Callable, checkout the methods wherein you can specify the timeout. E.g.

ExecutorService executor = Executors.newSingleThreadExecutor();
executor.invokeAll(Arrays.asList(new Task()), 10, TimeUnit.MINUTES); // Timeout of 10 minutes.
executor.shutdown();

Here Task of course implements Callable.

java killing a thread after timeout value

It's the same problem like this. Please use ExecutorService to execute the Runnable

How do I force terminate a thread in java with time limit?

Code snippet that I've used to do something similar:

 LOG.info("Time limited task started on monitored thread, with limit (" + limit + ")");
final ZonedDateTime start = nowUTC();
final Thread thread = new Thread(toRun);
thread.setDaemon(true);
final List<Throwable> exceptions = new ArrayList<>();
thread.setUncaughtExceptionHandler((t, e) -> {
exceptions.add(e);
});
thread.start();

// Check and wait for completion.
while (thread.isAlive()) {
if (!isWithinLimit(start, nowUTC())) {
LOG.error("Interrupting thread, did not complete before limit (" + limit + ")");
try {
thread.interrupt();
} catch (Exception e) {
e.printStackTrace();
}
throw new TimeLimitExceedException("Execution limit of " + limit
+ " exceeded. (Has been running since " + start + ")");
}
try {
Thread.sleep(POLLING_PERIOD.toMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// If it failed because of an exception, we want to trigger this.
if (!exceptions.isEmpty()) {
final Throwable exception = exceptions.get(0);
if (exception instanceof RuntimeException) {
throw (RuntimeException) exception;
} else {
throw new RuntimeException(exception);
}
}
final Duration runTime = Duration.between(start, nowUTC());
LOG.info("Time limited task has completed in (" + runTime + ") vs limit of (" + limit
+ ").");

TLDR:
I just start whatever I'm running as a new thread that is set as a daemon (just in case it is the last thing running), then I get a reference to that and poll it, and call thread.interrupt() if it goes over the time limit.

Other context & bells and whistles

  • This is part of a class that has some other state, like duration and what it is running
  • Also track some exceptions so that it can be spit out at the end if necessary

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.
}

How to limit a thread's execution time and terminate it if it runs too long?

I would use an ExecutorService to run the thread. Then I would get back a Future and use get() with a timeout to cancel it.

ExecutorService es = Executors.newFixedThreadPool(1); // You only asked for 1 thread
Future<?> future = es.submit( new Mythread() );
try {
future.get(timeout, TimeUnit.SECONDS); // This waits timeout seconds; returns null
} catch(TimeoutException e) {
future.cancel(true);
}

How to stop a thread after some time in java?

I don't know whether it is supported in Android, but this is exactly what the Future objects returned from an ExecutorService are supposed to do for you. In particular, the cancel(boolean) method can be used to interrupt the task if it has started but not finished.

The tasks should be written to be aware that they may be interrupted, and abort cleanly if they have been. Most of the framework IO methods can be interrupted, so you just need to worry about your own code.



Related Topics



Leave a reply



Submit