在Java中某些指定的时间限制之后终止线程

是否有一种方法来杀死一个在Java中的指定时间限制之后的子线程? 编辑:此特定的线程可能会在最坏的情况下被阻塞(线程用于等待文件修改,并阻塞,直到这个事件发生),所以我不知道中断()会成功?

使用ExecutorService来执行Runnable ,检出你可以指定超时的方法。 例如

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

这里Task当然实现了Runnable

为什么不在特定时间interrupt() ? 你生成的线程必须能够正确处理InterruptedException

请参阅这篇文章( http://www.javaspecialists.eu/archive/Issue056.html )以获得更多关于干净closures线程的信息。

另请参阅Executor / Future框架,它提供了在特定时间范围内收集结果和/或终止线程的有用方法。

不直接; 我认为最简单的方法就是在该线程上join()该时间限制,如果在连接结束时没有完成,则中断该线程。

所以,

 Thread t = ... t.join(timelimit); if (t.isAlive) t.interrupt(); 

注意我使用了中断,而不是实际上将其中断,这样更安全。 我也build议使用executors而不是直接操作线程。

您可以从jcabi-aspects (我是开发人员)为您的方法使用AOP和@Timeable注释:

 @Timeable(limit = 1, unit = TimeUnit.SECONDS) String load(String resource) { // do something time consuming } 

当达到时间限制时,线程将被interrupted()标志设置为true ,正确处理这种情况并停止执行是您的工作。 通常它由Thread.sleep(..)

由于与Thread的API文档相关的原因,杀死线程通常是一个糟糕的主意。

如果你已经死了杀死,使用一个全新的过程。

否则,通常情况下,让线程轮询System.nanoTime ,轮询一个(可能的volatile )标志,排队一个“毒丸”或某种性质的东西。

布赖恩的权利,打断它是比“停止”线程更安全。
如果线程在中间修改的对象上locking,并且突然停止(导致锁释放)呢? 你会得到奇怪的结果。

不要使用destroy()因为它不执行任何清理。

最简单的方法就是使用join()

 try { thread.join(); } catch (InterruptedException e) {//log exception...} 

你可以使用一个ExecutorService 。 如果您有多个线程同时运行,那么这将会很有意义。 如果在其他线程正在运行时需要产生新线程,可以将其与BlockingQueue结合使用。

ThreadPoolExecutorExecutorService实现)可以将BlockingQueue作为参数,只需将新线程添加到队列即可。 当你完成你只是终止ThreadPoolExecutor

 private BlockingQueue<Runnable> queue; ... ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, new Long(1000), TimeUnit.MILLISECONDS, this.queue); 

您可以保持添加到队列中的所有线程的计数。 当你认为你完成了(队列是空的,也许?)简单地比较这个

  if (issuedThreads == pool.getCompletedTaskCount()) { pool.shutdown(); } 

如果两者匹配,你就完成了。 终止池的另一种方法是在一个循环中等待一秒钟:

 try { while (!this.pool.awaitTermination(1000, TimeUnit.MILLISECONDS)); } catch (InterruptedException e) {//log exception...} 

自Java 9以来,在CompletableFuture中引入了一些有用的更改,作为JEP 266的一部分。使用orTimeout方法,现在可以像下面这样编写它:

 CompletableFuture.runAsync(thread::run) .orTimeout(30, TimeUnit.SECONDS) .exceptionally(throwable -> { log.error("An error occurred", throwable); return null; }); 

在Java 8中,不幸的是,你应该使用一些额外的代码。 以下是在龙目岛的帮助下委托模式使用情况的一个例子:

 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)); } } 

当然,上面的代码很容易被重写为静态的工厂方法:

 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); }