【问题标题】:ExecutorService - Killing thread after some specified time limitExecutorService - 在某个指定的时间限制后杀死线程
【发布时间】:2020-02-22 03:42:30
【问题描述】:

我创建了ExecutorService 并提交了一份工作。这项工作可能很耗时。所以我给了timeout 2 秒。如果执行时间超过 2 秒,我想杀死那个线程。

public void threadTest() {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        try {
            executor.submit(() -> {
                try {
                    String threadName = Thread.currentThread().getName();
                    Thread.sleep(7000);
                    System.out.println("process completed after 7 seconds");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).get(2, TimeUnit.SECONDS);
        }catch (Exception e){
        }
        executor.shutdown();

    }

    public static void main(String[] args) throws Exception {
        System.out.println("main start");
        ThreadBreaker tb = new ThreadBreaker();
        tb.threadTest();
        System.out.println("main end");
    }

输出

main start
main end
process completed after 7 seconds

函数threadTest 在 2 秒后退出,正如我所料。但是提交的作业继续运行。如果在给定的超时时间内无法完成,我想停止提交的任务。

【问题讨论】:

    标签: java threadpool runnable executorservice threadpoolexecutor


    【解决方案1】:

    一旦你向 executorService 提交了一个任务,你就会得到一个 Future 对象。您可以通过 Future.cancel(true) 调用取消执行。

    请记住,如果您在任务中进行了准确的 InterruptException 处理,则可以取消正在运行的任务。

    在上面的例子中:

     Thread.sleep(7000); 
    

    会引发一个中断的异常,你不应该捕捉它(或者如果你捕捉到它重新引发另一个异常)

    【讨论】:

      【解决方案2】:

      当你使用ExecutorService 时,你不能自己杀死线程。 ThreadPool 决定何时终止 Thread(通常在 Thread 被中断时可能会发生)。

      在您的情况下,您应该抓住TimeoutExceptioncancel Future。如果您的“真实”任务响应中断(正确调用和处理InterruptedException),它将起作用。否则,您应该在循环中检查Thread.currentThread().isInterrupted() 状态。 您的示例代码如下所示:

      public void threadTest() {
          ExecutorService executor = Executors.newSingleThreadExecutor();
          Future<?> submit = executor.submit(() -> {
              try {
                  String threadName = Thread.currentThread().getName();
                  Thread.sleep(7000);
                  System.out.println("process completed after 7 seconds");
              } catch (InterruptedException e) {
                  Thread.currentThread().interrupt(); //preserve interruption status. based on this ThreadPool's interruption Policy will decide what to do with the Thread
              }
          });
      
          try {
              submit.get(2, TimeUnit.SECONDS);
          } catch (InterruptedException | ExecutionException e) {
              e.printStackTrace(); //handle this
          } catch (TimeoutException e) {
              submit.cancel(true); //cancel the task
          }
          executor.shutdown();
      
      }
      

      还请记住,如果您在 ThreadPool 中执行任务,并且在大多数情况下执行可能来自 InterruptedException 的操作,您应该保留中断状态。

      【讨论】:

        猜你喜欢
        • 2011-02-13
        • 1970-01-01
        • 2011-06-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多