Is there a way to kill a child thread after some specified time limit in Java? Edit: Also this particular thread may be blocked in its worst case (Thread is used to wait for a file modification and blocks until this event occurs), so im not sure that interrupt() will be successful?
So, if the thread uses it to read a file, calling interrupt() on this thread blocked in the read method has no effect. However, we can explicitly check for the interrupt flag after every read in a loop. This will give a reasonable surety to stop the thread with some delay.
Whenever we want to stop a thread from running state by calling stop() method of Thread class in Java. This method stops the execution of a running thread and removes it from the waiting threads pool and garbage collected.
Modern ways to suspend/stop a thread are by using a boolean flag and Thread. interrupt() method. Using a boolean flag: We can define a boolean variable which is used for stopping/killing threads say 'exit'. Whenever we want to stop a thread, the 'exit' variable will be set to true.
In Java threads are not killed, but the stopping of a thread is done in a cooperative way. The thread is asked to terminate and the thread can then shutdown gracefully. Often a volatile boolean field is used which the thread periodically checks and terminates when it is set to the corresponding value.
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
.
Some helpful changes were introduced as part of JEP 266 in CompletableFuture
since Java 9. Using orTimeout method, for now, it is possible to write it like:
CompletableFuture.runAsync(thread::run) .orTimeout(30, TimeUnit.SECONDS) .exceptionally(throwable -> { log.error("An error occurred", throwable); return null; });
In Java 8, unfortunately, you should use some extra code. Here is an example of delegation pattern usage with help of Lombok:
import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.time.Duration; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executors; import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.concurrent.TimeoutException; import static lombok.AccessLevel.PRIVATE; import lombok.AllArgsConstructor; import lombok.experimental.Delegate; @AllArgsConstructor(access = PRIVATE) public class TimeoutableCompletableFuture<T> extends CompletableFuture<T> { public static TimeoutableCompletableFuture<Void> runAsync( Runnable runnable) { return new TimeoutableCompletableFuture<>( CompletableFuture.runAsync(runnable)); } @Delegate private final CompletableFuture<T> baseFuture; public TimeoutableCompletableFuture<T> orTimeout(Duration duration) { final CompletableFuture<T> otherFuture = new CompletableFuture<>(); Executors.newScheduledThreadPool( 1, new ThreadFactoryBuilder() .setDaemon(true) .setNameFormat("timeoutable-%d") .build()) .schedule(() -> { TimeoutException ex = new TimeoutException( "Timeout after " + duration); return otherFuture.completeExceptionally(ex); }, duration.toMillis(), MILLISECONDS); return new TimeoutableCompletableFuture<>( baseFuture.applyToEither(otherFuture, a -> a)); } }
Of course, the code above easily could be rewritten as just a static factory method:
public static CompletableFuture<Void> runAsyncOrTimeout( Runnable runnable, long timeout, TimeUnit unit) { CompletableFuture<Void> other = new CompletableFuture<>(); Executors.newScheduledThreadPool( 1, new ThreadFactoryBuilder() .setDaemon(true) .setNameFormat("timeoutafter-%d") .build()) .schedule(() -> { TimeoutException ex = new TimeoutException( "Timeout after " + timeout); return other.completeExceptionally(ex); }, timeout, unit); return CompletableFuture.runAsync(runnable).applyToEither(other, a -> a); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With