【问题标题】:What is the purpose of ScheduledFuture.get() method if is retrieved from the scheduleWithFixedDelay/scheduleAtFixedRate method如果从 scheduleWithFixedDelay/scheduleAtFixedRate 方法中检索 ScheduledFuture.get() 方法的目的是什么
【发布时间】:2014-07-31 00:16:39
【问题描述】:

我对以下内容感到困惑。

我知道,如果我使用 ScheduledThreadPoolExecutor 类中的 schedule 方法:

ScheduledFuture<?> scheduledFuture = 
scheduledThreadPoolExecutor.schedule(myClassRunnable, 5, TimeUnit.SECONDS);

我以后可以通过 value scheduledFuture.get(5, TimeUnit.SECONDS)scheduledFuture.get() 应该是 null 因为任务只执行了一次就完成了。 还有null,因为我正在使用Runnable schedule 方法版本而不是Callable schedule 方法版本。符合API。

直到这里我都很好。

我的问题:

如果从scheduleWithFixedDelay(甚至是scheduleAtFixedRate)方法中检索到ScheduledFuture,其用途是什么:

ScheduledFuture<?> scheduledFuture= 
scheduledThreadPoolExecutor.scheduleWithFixedDelay(myClassRunnable, 1, 5, TimeUnit.SECONDS);

是的,我知道两个 fixed 方法都会多次执行同一个任务,直到调用 ScheduledThreadPoolExecutor's shutdown 方法(它必须停止所有计划的任务)。

我通过 Google 进行了一项研究,寻找一些使用从 scheduleWithFixedDelay 返回的 ScheduledFuture 的示例,我只找到了一个使用 cancel 方法取消特定任务的示例。但是没有人使用get()

我不知道我是否错了,但如果我们使用scheduleWithFixedDelayget() 方法似乎没用,因为如果我稍后使用:

  • scheduledFuture.get() - 它仍在等待,Runnable 对象仍然工作多次(运行、完成、延迟、运行等...)
  • scheduledFuture.get(32, TimeUnit.SECONDS) - 总是给出TimeoutException

我认为我应该能够检索null 值,因为我可以使用scheduleWithFixedDelay 方法中的period 参数/参数。即:运行Runnable object,等待它完成并使用scheduledFuture.get()获取确认它已经完成的null值,等待延迟时间再次运行Runnable对象根据period值等......

完全欢迎澄清和举例。

【问题讨论】:

    标签: java java.util.concurrent


    【解决方案1】:

    ScheduledFuture 可用于获取下一个任务执行前的剩余时间:

        ScheduledFuture<?> f = Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
            public void run() {
                System.out.println("run");
            }
        }, 0, 10000, TimeUnit.MILLISECONDS);
        Thread.sleep(1000);
        System.out.println("Time left before next run " + f.getDelay(TimeUnit.MILLISECONDS));
    

    打印

    run
    Time left before next run 8999
    

    【讨论】:

    • 感谢您的回复和代码,好吧有道理,只是想知道您是否遇到了将 ScheduledFuture 的 get 方法与 scheduleAtFixedRate/scheduleWithFixedDelay 一起使用的情况。谢谢。
    • 没有真正回答 OP 问题What is the purpose of ScheduledFuture.get() method
    【解决方案2】:

    我用下面的代码试了一下:

    ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
    AtomicInteger count = new AtomicInteger(0);
    Runnable task = () -> {
        int currentCount = count.incrementAndGet();
        System.out.println("Task #" + currentCount + " started");
        if (currentCount == 2) {
            System.out.println("Shutting down scheduler...");
            scheduler.shutdown();
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ie) {
            throw new RuntimeException(ie);
        }
        System.out.println("Task #" + currentCount + " finished");
    };
    
    System.out.println("Starting scheduler...");
    ScheduledFuture<?> scheduledFuture = scheduler.scheduleWithFixedDelay(
        task, 0, 2, TimeUnit.SECONDS);
    System.out.println("Getting scheduled future...");
    System.out.println(scheduledFuture.get());        
    System.out.println("End of code reached.");
    

    这是输出:

    Exception in thread "main" java.util.concurrent.CancellationException
        at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:121)
        at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
        at Rextester.main(source.java:33)
    Starting scheduler...
    Getting scheduled future...
    Task #1 started
    Task #1 finished
    Task #2 started
    Shutting down scheduler...
    Task #2 finished
    

    在线 Rextester 演示: https://rextester.com/LYKN32123

    不确定这有多大用处,但它表明如果调度程序关闭,get() 方法会抛出 CancellationException

    【讨论】:

      【解决方案3】:

      我认为在使用.scheduleWithFixedDelay(...)(或scheduleAtFixedRate(...))的情况下,返回的get() 方法确实感觉很奇怪。

      我相信你永远不会从 get() 方法中收到任何东西,只是希望在 Runnable 被取消时会引发异常。

      当然可以看到一个用例 ;-)

      参见 JavaDoc

      https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ScheduledExecutorService.html#scheduleAtFixedRate-java.lang.Runnable-long-long-java.util.concurrent.TimeUnit-

      返回: 一个 ScheduledFuture 表示任务的挂起完成,其 get() 方法将在取消时抛出异常

      【讨论】:

        【解决方案4】:

        使用 scheduleFuture.get() 您可以获得任务的句柄,如果需要从 UserInterface 手动取消此任务或基于 null 等条件,可以使用句柄取消它。

        【讨论】:

        • scheduledFuture.cancel(bool) 是用来取消Runnable
        猜你喜欢
        • 2014-08-30
        • 2011-06-29
        • 2014-07-14
        • 2011-02-26
        • 2013-02-10
        • 2014-02-03
        • 2022-10-13
        • 2010-10-11
        相关资源
        最近更新 更多