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