我希望得到您对以下问题和解决方案(潜在)的反馈。
假设有一个Runnable任务对CPU使用情况进行采样并将其写入CSV文件。此任务不会返回任何结果。这需要安排永久定期执行。如果用户取消任务,我们关闭文件编写器,用户可以下载CSV文件。
当您向ListeningScheduledExecutorService提交此类任务时(如下所示),您将获得一个表示任务结果的ListenableScheduledFuture。
ListenableScheduledFuture<Void> future = (ListenableScheduledFuture<Void>) scheduledExecutorService
.scheduleAtFixedRate(task, initialDelay, interval, timeUnit);
我们在未来注册回调,以便在任务取消后,CSV文件可供下载:我们需要将ListenableScheduledFuture转换为ListenableScheduledFuture。
Function<Void, File> transformFunc = new Function<Void, File>()
{
@Override
public File apply(Void arg0)
{
return file;
}
};
ListenableScheduledFuture<File> futureToListen = (ListenableScheduledFuture<File>) Futures.transform(future, transformFunc);
// register a callback to the ListenableScheduledFuture<File>
Futures.addCallback(futureToListen, callback, executorService);
注意:根据Guava API DOC 1,取消futureToListen会导致我们的任务被取消。
问题:
因为任务结果无效,如上所示投射到ListenableScheduledFuture是否有意义?
将返回void的任务的未来转换为某种类型的未来在语义上是否有意义?
是否有更好,更优雅的解决方案?使用Java8的CompletableFuture会不会更好?
答案 0 :(得分:1)
transform
可能不会做你想要的。您提到取消futureToListen
将取消future
,这是真的。问题是保留区也是如此:取消future
时,futureToListen
也会被取消。这意味着它永远不会计算其结果。
要解决此问题,您有几个选择:
future
,请将futureToListen
更改为SettableFuture
。然后,取消future
的人也可以致电futureToListen.set(file)
。future
,请将futureToListen
更改为AbstractFuture
,(a)公开set()
(以便您可以执行我的操作)推荐在(1))和(b)实施interruptTask()
来呼叫future.cancel()
。还有其他可能的聪明解决方案涉及在future
完成失败时触发工作,但我不确定我是否会推荐。我个人对使用&#34感到有些紧张; Future
被取消&#34;作为&#34;工作成功完成的信号。&#34;这是因为Future
也可以被执行器关闭取消,例如。 (另一个原因是:您需要小心区分&#34;在执行期间抛出异常&#34;并且&#34;被取消。&#34;)因此,我建议的解决方案已设置最多直接拨打set()
,而不是触发取消未来。