Tra*_*ker 32 java multithreading
有没有办法在Java中指定的时间限制后杀死子线程?编辑:此特定线程也可能在最坏的情况下被阻止(线程用于等待文件修改并阻塞直到发生此事件),所以我不确定interrupt()是否会成功?
Bal*_*usC 40
利用ExecutorService
执行Callable
,签出可以指定超时的方法.例如
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.invokeAll(Arrays.asList(new Task()), 10, TimeUnit.MINUTES); // Timeout of 10 minutes.
executor.shutdown();
Run Code Online (Sandbox Code Playgroud)
这Task
当然是实现的Callable
.
一些有用的变化是引入的一部分JEP 266在CompletableFuture
从Java 9.使用orTimeout方法,现在,就可以直接写成:
CompletableFuture.runAsync(thread::run)
.orTimeout(30, TimeUnit.SECONDS)
.exceptionally(throwable -> {
log.error("An error occurred", throwable);
return null;
});
Run Code Online (Sandbox Code Playgroud)
不幸的是,在 Java 8 中,您应该使用一些额外的代码。以下是在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));
}
}
Run Code Online (Sandbox Code Playgroud)
当然,上面的代码可以很容易地重写为静态工厂方法:
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);
}
Run Code Online (Sandbox Code Playgroud)
为什么不在interrupt()
特定的时间之后呢?你的衍生线程必须能够InterruptedException
正确处理.
有关干净地关闭线程的更多信息,请参阅此文章(http://www.javaspecialists.eu/archive/Issue056.html).
另请参见Executor/Future框架,它提供了在特定时间限制内收集结果和/或终止线程的有用方法.
不直接;我认为最简单的方法是在具有该时间限制的线程上 join() ,如果在 join 结束时还没有完成,则中断线程。
所以,
Thread t = ...
t.join(timelimit);
if (t.isAlive()) t.interrupt();
Run Code Online (Sandbox Code Playgroud)
注意我使用了中断而不是实际杀死它,它更安全。我还建议使用执行程序而不是直接操作线程。