【问题标题】:Utility of Future.cancel(boolean) methodFuture.cancel(boolean) 方法的实用程序
【发布时间】:2012-03-02 16:11:00
【问题描述】:

我只是在探索 java.util.concurrent 包。

我了解到类 'Future' 有一个方法 boolean cancel(boolean mayInterruptIfRunning)

请附上我写的测试代码:

package com.java.util.concurrent;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;

public class FutureTester {

/**
 * @param args
 * @throws InterruptedException
 */
public static void main(String[] args) throws InterruptedException {
    // TODO Auto-generated method stub
    int poolCnt = 1;
    Callable<NumberPrinter> numberPrinter = null;
    ScheduledThreadPoolExecutor schPool = new ScheduledThreadPoolExecutor(
            poolCnt);
    ScheduledFuture<NumberPrinter>[] numPrinterFutures = new ScheduledFuture[poolCnt];
    FutureTask<NumberPrinter>[] futureTask = new FutureTask[poolCnt];

    for (int i = 0; i < poolCnt; i++) {
        numberPrinter = new NumberPrinter();
        futureTask[i] = new FutureTask<NumberPrinter>(numberPrinter);

        /*
         * numPrinterFutures[i] = (ScheduledFuture<NumberPrinter>) schPool
         * .schedule(futureTask[i], 0, TimeUnit.MILLISECONDS);
         */
        numPrinterFutures[i] = (ScheduledFuture<NumberPrinter>) schPool
                .submit(futureTask[i]);
    }

    //Thread.sleep(30);

    if (numPrinterFutures.length > 0) {

        System.out.println("Task completed ? "
                + numPrinterFutures[0].isDone());

        System.out.println("Task cancelled ? "
                + numPrinterFutures[0].cancel(true));

        System.out.println("Is task cancelled ? "
                + numPrinterFutures[0].isCancelled());
    }
}

}

class NumberPrinter implements Callable<NumberPrinter> {

private int counter = 10;

@Override
public NumberPrinter call() throws Exception {
    // TODO Auto-generated method stub

    while (counter > 0) {
        if (Thread.interrupted()) {/*OUCH !!!*/
            return null;
        }
        System.out.println("counter = " + (counter--));
    }

    return this;
}

}

最初,我假设取消任务也会停止正在运行的线程的执行(不包括“OUCH”部分)。但我得到的输出为如下:

counter = 10
Task completed ? false
counter = 9
Task cancelled ? true
counter = 8
Is task cancelled ? true
counter = 7
counter = 6
counter = 5
counter = 4
counter = 3
counter = 2
counter = 1

在进一步阅读stackoverflow本身时,据说

  1. “取消”方法只能停止“未启动”的作业(与方法的api描述相矛盾)
  2. cancel 方法只是中断正在运行的线程,然后 必须从 run() 方法返回

因此,我包含了 'OUCH' 部分 - 一个 while 循环检查中断;输出如下:

Task completed ? false
counter = 10
Task cancelled ? true
Is task cancelled ? true

问题:

如果应该编写类似于“OUCH”部分的内容来停止正在运行的线程,那么取消方法的实用程序/价值是什么。如果无法通过取消来停止线程,将 Callable 包装在 FutureTask 中有何帮助?我忽略的设计/概念/逻辑部分是什么?

【问题讨论】:

  • 我遇到了同样的问题。我不知道为什么我的线程池在某个时候会耗尽。现在我想通了为什么。谢谢。

标签: java multithreading future futuretask


【解决方案1】:

如果无法通过取消来停止线程,将 Callable 包装在 FutureTask 中有何帮助?

您想取消任务,而不是运行它的线程。使用 cancel(true) 可防止任务启动(但不会将其从队列中删除)并在任务已启动时中断线程。任务可以忽略中断,但是没有干净的方法可以在不杀死整个进程的情况下杀死线程。

【讨论】:

    【解决方案2】:

    您忽略的问题是在 Java 中只有协作线程才能安全停止。

    确实,如果您查看 Thread API,您会注意到有一些称为 destroypausestopresume 的方法在 Java 1.1 中已被弃用。它们被弃用的原因是 Java 设计者意识到它们通常不能安全使用。原因在注释"Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?"中解释。

    这个问题是 Java 线程模型中固有的,只能通过减少一个线程与其他线程使用的对象交互的能力来避免。有一个 JSR 指定了一种执行此操作的方法……隔离……但据我所知,没有主流 JVM 实现这些 API。


    所以回到你的问题,Future.cancel 的用处在于它解决了可以在期货上下文中解决的问题的子集。

    【讨论】:

      【解决方案3】:

      如果 Future 尚未运行,则调用 cancel(true) 将阻止执行,如果当前正在运行,则将是 interrupted。此时,取消Future 的负担就落在了开发者身上。

      因为它是一个线程池,所以停止线程是没有意义的(尽管停止线程很少有意义)。取消/中断不会导致线程退出其运行方法。在执行 Callable 的 call 方法后,它会简单地将下一个项目从工作队列中拉出并进行处理。

      cancel 方法的实用性只是向执行线程发出信号,表明某个进程希望 Callable 停止 - 而不是线程 - 所以您必须自己处理 Callable 的停止。

      【讨论】:

      • 这真的比其他答案更有帮助:)
      【解决方案4】:

      假设,作为未来一部分运行的代码不支持协作取消或中断。那么取消一个未开始的任务是你能做的最好的事情。这就是存在这种方法的原因。

      总的来说,我认为取消是严格合作的。仅仅强行取消一段代码可能会导致损坏状态。

      【讨论】:

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