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