Future<T> 与在 Java Executor Service 中扩展 Task<T> 的 Class 不兼容

Future<T> not compatible with Class that extends Task<T> in Java Executor Service

我的 class DownloadTask 扩展 javafx.concurrent.Task<Boolean>

将我的任务提交给 ExecutorService 后,我尝试将结果分配给 Future<Boolean> 类型的变量。但是,IDE 警告我,我的实例化对象具有通用类型 <capture<?>>,我不知道为什么。

我的classDownloadTask:

import javafx.concurrent.Task;

private class DownloadTask extends Task<Boolean>{
    public DownloadTask() {}

    @Override
    protected Boolean call() throws Exception {
         return true;
    }
}

我是如何管理线程池的:

ExecutorService executor = Executors.newFixedThreadPool(10);
ArrayList<Future<Boolean>> resultList = new ArrayList<>();

for (ScheduleRow scheduleRow : queArray) {
    DownloadTask downloadTask = new DownloadTask();

    Future<Boolean> result = executor.submit(downloadTask); //incompatible types

    resultList.add(result);
}

executor.shutdown();

根据 javafx.concurrent.Task 的 Javadoc,Task 实现了 Runnable,而不是 Callable<T>

因此,当您将它提交给 ExecutorService 时,它会被视为没有 return 值的东西,因此生成的未来是 Future<?>

要么使用特定于 javafx 的 ExecutorService(不知道是否有专门用于 Task 的);或者让您的 class 实施 Callable<Boolean>

简答

要解决该警告,您可以只需添加类型信息以启用类型推断:

Future<Boolean> result = executor.submit(downloadTask, true);

但是请注意,对于 result 变量,Futureget 方法将 return 给定的 true 成功完成后,因为 DownloadTask 被解释为不产生结果的 Runnable。正如 Mike Strobel 所说,更好的方法是从 DownloadTask 本身获得正确的结果,因为它也是 Future<Boolean>:

executor.submit(downloadTask);
resultList.add(downloadTask);

长答案

正如 Andy Turner 所说,javafx.concurrent.Task 的继承类型是 Runnable(因为它扩展 FutureTask 实现 RunnableFuture)。

将此传递给 ExecutorServiceFuture<?> submit(Runnable task) 方法将产生 Future<?> 结果,而 IDE 将抛出令人讨厌的 Future<capture<?>>.

但是,您不需要特定于 javafx 的 ExecutorServicejava.util.concurrent.ExecutorService 可以正常工作,因为 DownloadTaskFutureTask.[=41 的子类=]

要修复类型推断,您可以使用 java.util.concurrent.ExecutorService 的泛型 <T> Future<T> submit(Runnable task, T result) 方法。由于它是一个简单的布尔值,您可以依靠自动装箱:

Future<Boolean> result = executor.submit(downloadTask, true);

问题是,对于 result 变量,Future 的 get 方法将 return 给定的 true 成功完成。在您的示例中,结果 Future 上的 get 方法将始终 return null。这是因为它被解释为不产生结果的 Runnable。正如 Mike Strobel 所说,更好的方法是从 DownloadTask 本身获得正确的结果,因为它也是一个 Future:

executor.submit(downloadTask);
resultList.add(downloadTask);

你真的不需要对 submit 的结果做任何事情;你的 DownloadTask 已经 一个 Future<Boolean>,当它运行时,它会设置自己的结果。 submit 返回的 Future<?> 无论如何都无法转发您的任务结果,因为它只是将其视为不产生值的 Runnable

只需更改此:

Future<Boolean> result = executor.submit(downloadTask);
resultList.add(result);

为此:

executor.submit(downloadTask);
resultList.add(downloadTask);