我的类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
变量,Future
的get
方法将在成功完成时返回给定的true,因为DownloadTask
被解释为不会产生结果的Runnable
。正如Mike Strobel所说,更好的方法是从DownloadTask
本身获得正确的结果,因为它也是Future<Boolean>
:
executor.submit(downloadTask);
resultList.add(downloadTask);
长答案
正如Andy Turner所说,javafx.concurrent.Task
的继承类型是Runnable
(因为它扩展了实现RunnableFuture
的FutureTask
)。
将其传递给ExecutorService
的Future<?> submit(Runnable task)
方法将产生Future<?>
结果,IDE将抛出那个讨厌的Future<capture<?>>
。
但是,您不需要特定于javafx的ExecutorService
,java.util.concurrent.ExecutorService
工作得很好,因为DownloadTask
是FutureTask
的子类。
要修复类型推断,可以使用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);