java Future.cancel() 方法不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13623445/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 13:25:55  来源:igfitidea点击:

Future.cancel() method is not working

javaconcurrencyinterruptinterrupt-handlinginterrupted-exception

提问by Ismail Shaik

The code that I have creates a Callable instance and using ExecutorService a new thread is being created. I want to kill this thread after certain amount of time if the thread is not done with its execution. After going through the jdk documentation I've realized that Future.cancel() method can be used to stop the execution of the thread, but to my dismay its not working. Of course future.get() method is sending an interrupt to the Thread after the stipulated time (in my case its 2 seconds) and even the thread is receiving this interrupt but this interruption is taking place only once the thread is done with its execution completely. But I want to kill the thread after 2 seconds.

我创建的代码创建了一个 Callable 实例并使用 ExecutorService 创建了一个新线程。如果线程未完成执行,我想在一定时间后终止该线程。在浏览了 jdk 文档后,我意识到 Future.cancel() 方法可用于停止线程的执行,但令我失望的是它不起作用。当然,future.get() 方法会在规定的时间(在我的情况下为 2 秒)之后向线程发送中断,甚至线程也正在接收此中断,但仅在线程完成执行后才会发生此中断完全地。但我想在 2 秒后终止线程。

Could anyone help me how to achieve this.

谁能帮助我如何实现这一目标。

Testclass code:

测试类代码:

====================================

public class TestExecService {

      public static void main(String[] args) {

          //checkFixedThreadPool();
          checkCallablePool();

          }

      private static void checkCallablePool()
      {
          PrintCallableTask task1 = new PrintCallableTask("thread1");

          ExecutorService threadExecutor = Executors.newFixedThreadPool(1);
          Future<String> future = threadExecutor.submit(task1);

          try {
                System.out.println("Started..");
                System.out.println("Return VAL from thread ===>>>>>" + future.get(2, TimeUnit.SECONDS));
                System.out.println("Finished!");
            }
          catch (InterruptedException e) 
          {
            System.out.println("Thread got Interrupted Exception ==============================>>>>>>>>>>>>>>>>>>>>>>>>>");
            //e.printStackTrace();
          }
          catch (ExecutionException e) 
          {
            System.out.println("Thread got Execution Exception ==============================>>>>>>>>>>>>>>>>>>>>>>>>>");
          }
          catch (TimeoutException e)
          {
            System.out.println("Thread got TimedOut Exception ==============================>>>>>>>>>>>>>>>>>>>>>>>>>");
            future.cancel(true);
          }

          threadExecutor.shutdownNow();

      }
}

Callable Class code:

可调用类代码:

===================================================================
package com.test;

import java.util.concurrent.Callable;

public class PrintCallableTask implements Callable<String> {

      private int sleepTime;
      private String threadName;

    public PrintCallableTask(String name)
    {
        threadName = name;
        sleepTime = 100000;     
    }

    @Override
    public String call() throws Exception {

        try {
              System.out.printf("%s going to sleep for %d milliseconds.\n", threadName, sleepTime);
              int i = 0;

              while (i < 100000)
              {
                  System.out.println(i++);
              }


              Thread.sleep(sleepTime); // put thread to sleep
              System.out.printf("%s is in middle of execution \n", threadName);

            } catch (InterruptedException exception) {
              exception.printStackTrace();
            }


            System.out.printf("%s done sleeping\n", threadName);

            return "success";
    }

}

回答by

Your code does everything right. The only problem is that you're not checking Thread.isInterruptedin the whileloop. The only way for thread to get the message is to get to the blocking call Thread.sleepwhich will immediately throw InterruptedException. If loop is lengthy it can take some time. That's exactly why your code is a little bit unresponsive.

你的代码做的一切都是正确的。唯一的问题是你没有Thread.isInterruptedwhile循环中检查。线程获取消息的唯一方法是访问Thread.sleep将立即抛出的阻塞调用InterruptedException。如果循环很长,则可能需要一些时间。这正是您的代码有点无响应的原因。

Check for interruption status, say, every 10,000 iterations:

检查中断状态,例如每 10,000 次迭代:

while (i < 100000) {

    if (i % 10000 == 0 && Thread.currentThread().isInterrupted())
        return "fail";

    System.out.println(i++);
}

InterruptedExceptionis for lengthy blocking methods. Thread.isInterruptedis for everything else.

InterruptedException用于冗长的阻塞方法。Thread.isInterrupted是为了其他一切。

回答by Vadzim

cancel()just calls interrupt()for already executing thread.

cancel()只是调用interrupt()已经在执行的线程。

http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html:

http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html

An interrupt is an indication to a thread that it should stop what it is doing and do something else. It's up to the programmer to decide exactly how a thread responds to an interrupt, but it is very common for the thread to terminate.

中断是对线程的指示,它应该停止正在执行的操作并执行其他操作。由程序员决定线程如何准确响应中断,但线程终止是很常见的。

Interrupted thread would throw InterruptedExceptiononly

中断线程会抛出InterruptedException的唯一

when a thread is waiting, sleeping, or otherwise paused for a long time and another thread interrupts it using the interrupt() method in class Thread.

当一个线程长时间等待、休眠或以其他方式暂停并且另一个线程使用 Thread 类中的 interrupt() 方法中断它时。

So you need to explicitly make job code in executing thread aware of possible interruption.

所以你需要在执行线程时明确地让作业代码意识到可能的中断。

See also Who is calling the Java Thread interrupt() method if I'm not?.

另请参阅如果我不是,谁在调用 Java 线程中断() 方法?.

See also How to cancel Java 8 completable future?as java futures matured only by Java 8.

另请参阅如何取消 Java 8 可完成的未来?因为只有 Java 8 才使 Java 期货成熟。