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

时间:2018-06-11 23:37:14

标签: java terminate

我正在尝试找到一种方法来设置运行代码块的时间限制(在时间到期时强制终止它),而不修改代码块的内部。这是我尝试做的事情:我首先从此链接复制了TimeLimitedCodeBlock类: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);
      }
    }
  }

}

以下是我使用上面定义的类运行的内容:

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

并没有终止。我应该如何解决它以便它终止?

1 个答案:

答案 0 :(得分:0)

我曾经做过类似的代码片段:

 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()如果它超过了时间限制。

其他背景&amp;钟声和口哨

  • 这是具有其他状态的类的一部分,例如持续时间和正在运行的状态
  • 还跟踪一些例外情况,以便在必要时可以在最后吐出