将ListenableScheduledFuture <void>转换为ListenableFuture <somethingelse> </somethingelse> </void>

时间:2014-05-15 19:07:27

标签: java guava

我希望得到您对以下问题和解决方案(潜在)的反馈。

假设有一个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会导致我们的任务被取消。

问题:

  1. 因为任务结果无效,如上所示投射到ListenableScheduledFuture是否有意义?

  2. 将返回void的任务的未来转换为某种类型的未来在语义上是否有意义?

  3. 是否有更好,更优雅的解决方案?使用Java8的CompletableFuture会不会更好?

1 个答案:

答案 0 :(得分:1)

transform可能不会做你想要的。您提到取消futureToListen将取消future,这是真的。问题是保留区也是如此:取消future时,futureToListen也会被取消。这意味着它永远不会计算其结果。

要解决此问题,您有几个选择:

  1. 如果您不关心是否可以取消future,请将futureToListen更改为SettableFuture。然后,取消future的人也可以致电futureToListen.set(file)
  2. 如果您确实想要取消future,请将futureToListen更改为AbstractFuture,(a)公开set()(以便您可以执行我的操作)推荐在(1))和(b)实施interruptTask()来呼叫future.cancel()
  3. 还有其他可能的聪明解决方案涉及在future完成失败时触发工作,但我不确定我是否会推荐。我个人对使用&#34感到有些紧张; Future被取消&#34;作为&#34;工作成功完成的信号。&#34;这是因为Future也可以被执行器关闭取消,例如。 (另一个原因是:您需要小心区分&#34;在执行期间抛出异常&#34;并且&#34;被取消。&#34;)因此,我建议的解决方案已设置最多直接拨打set(),而不是触发取消未来。