将来<T>与<T>扩展 Java 执行器服务中任务的类不兼容



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

在将任务提交给ExecutorService之后,我尝试将结果分配给Future<Boolean>类型的变量。然而,IDE警告我,我的实例化对象有一个泛型类型<capture<?>>,我不知道为什么。

我的班级DownloadTask:

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

简短回答

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

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

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

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

长答案

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

将其传递给ExecutorServiceFuture<?> submit(Runnable task)方法将产生Future<?>结果,IDE将抛出那个讨厌的Future<capture<?>>

但是,您不需要特定于javafx的ExecutorServicejava.util.concurrent.ExecutorService工作得很好,因为DownloadTaskFutureTask的子类。

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

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

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

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

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

因此,当您将它提交给ExecutorService时,它被视为不返回值的东西,因此产生的future是Future<?>

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

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

只需更改:

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

对此:

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

最新更新