如何在 java 中强制终止有时间限制的线程?

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

我正在尝试找到一种方法来为 运行 代码块设置时间限制(当时间到了时强制终止它)而不修改代码块的内部结构。这是我尝试做的事情:我首先从这个 link 复制了 TimeLimitedCodeBlock class:Java-how-to-set-timeout

import java.util.*;
import java.util.concurrent.*;
public class TimeLimitedCodeBlock {

  public static void runWithTimeout(final Runnable runnable, long timeout, TimeUnit timeUnit) throws Exception {
    runWithTimeout(new Callable<Object>() {
      @Override
      public Object call() throws Exception {
        runnable.run();
        return null;
      }
    }, timeout, timeUnit);
  }

  public static <T> T runWithTimeout(Callable<T> callable, long timeout, TimeUnit timeUnit) throws Exception {
    final ExecutorService executor = Executors.newSingleThreadExecutor();
    final Future<T> future = executor.submit(callable);
    executor.shutdown(); // This does not cancel the already-scheduled task.
    try {
      return future.get(timeout, timeUnit);
    }
    catch (TimeoutException e) {
      future.cancel(true);
      throw e;
    }
    catch (ExecutionException e) {
      Throwable t = e.getCause();
      if (t instanceof Error) {
        throw (Error) t;
      } else if (t instanceof Exception) {
        throw (Exception) t;
      } else {
        throw new IllegalStateException(t);
      }
    }
  }

}

这是我 运行 使用上面定义的 class 的结果:

public static void main(String [] args)
    {
            try{
                    TimeLimitedCodeBlock.runWithTimeout(new Runnable()
                                    {

                                    public void run()
                                    {
                                    try{
                                        while(true){}
                                    }catch(Exception e){}
                                    }},1,TimeUnit.SECONDS);
            }
            catch(Exception e){}
    }

它不会终止。我应该如何修复它才能终止?

我用来做类似事情的代码片段:

 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: 我只是将我 运行 作为一个设置为守护进程的新线程启动(以防万一它是最后一件事 运行),然后我得到一个引用并轮询它,然后如果超过时间限制,调用 thread.interrupt()。

其他背景和花里胡哨

  • 这是 class 的一部分,它有一些其他状态,比如持续时间和它是什么 运行
  • 也跟踪一些异常,以便在必要时在最后吐出