【问题标题】:Future.cancel() method is not workingFuture.cancel() 方法不起作用
【发布时间】:2012-11-29 10:15:29
【问题描述】:

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

谁能帮我实现这个目标。

测试类代码:

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

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

      }
}

可调用类代码:

===================================================================
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";
    }

}

【问题讨论】:

    标签: java concurrency interrupt interrupt-handling interrupted-exception


    【解决方案1】:

    您的代码一切正常。唯一的问题是您没有在while 循环中检查Thread.isInterrupted。线程获取消息的唯一方法是访问阻塞调用Thread.sleep,它将立即抛出InterruptedException。 如果循环很长,则可能需要一些时间。这正是您的代码有点反应迟钝的原因。

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

    while (i < 100000) {
    
        if (i % 10000 == 0 && Thread.currentThread().isInterrupted())
            return "fail";
    
        System.out.println(i++);
    }
    

    InterruptedException 用于冗长的阻塞方法。 Thread.isInterrupted 用于其他所有内容。

    【讨论】:

    • 如果我无法控制 Runnable 怎么办? (它在第三方库中?)
    【解决方案2】:

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

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

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

    中断的线程只会抛出InterruptedException

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

    因此,您需要在执行线程时明确地使作业代码意识到可能的中断。

    另见Who is calling the Java Thread interrupt() method if I'm not?

    另请参阅 How to cancel Java 8 completable future?,因为只有 Java 8 才能成熟的 Java 期货。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-25
    • 1970-01-01
    • 1970-01-01
    • 2016-05-25
    • 2016-01-07
    相关资源
    最近更新 更多