代码之家  ›  专栏  ›  技术社区  ›  Nathan Feger

为什么Java的scheduleWithFixedDelay可以处理Runnable而不是FutureTask<?>包装Runnable?

  •  6
  • Nathan Feger  · 技术社区  · 15 年前

    为什么Java的scheduleWithFixedDelay可以处理Runnable而不是包装Runnable的FutureTask?

    使用两个不同的代码示例可以很容易地显示这一点:

    ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
            executorService.scheduleWithFixedDelay(new FutureTask<Integer>(new Callable<Integer>() {
    
                @Override
                public Integer call() throws Exception {
                    System.out.println("beep");
                    return 1;
                }
            }), 1, 5, TimeUnit.SECONDS);
    

    但是应用程序没有退出,它只是等待。

    但是:

    ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
        executorService.scheduleWithFixedDelay(new Runnable() {
    
            @Override
            public void run() {
                System.out.println("beep ");
            }
        }, 1, 5, TimeUnit.SECONDS);
    

    生产:

    嘟嘟声 嘟嘟声

    好像这里发生了某种锁,我无法确定。

    2 回复  |  直到 15 年前
        1
  •  13
  •   Andrzej Doyle    15 年前

    因为你在虐待我 FutureTask

    根据Javadocs,FutureTask是“可取消的异步计算”,但更通俗地说,它包装了Runnable/Callable的特定执行以提供异步性。我其实没有意识到 Runnable 直到我刚才检查了-的执行情况 run()

    因此,在第一个示例中发生的是,您正在调度未来的任务,它的run方法在1秒后被调用,因此它计算计算结果(即运行嵌入的

    我认为这里的根本问题是,直接安排未来的任务似乎没有意义,至少不是以你现在的方式。如果您希望每五秒钟运行一段代码,那么您肯定应该采用第二种方法。未来任务包含一个(单个!)计算;没有理由希望它被多次调用,事实上它专门缓存结果来防止这种情况。

        2
  •  3
  •   skaffman    15 年前

    FutureTask 将对象放入 ScheduledExecutorService ,你应该进去 Runnable Callable ,那么 退货 你是一个 . 事实上 未来任务 实现 可运行的 接口似乎是一个不幸的设计缺陷,允许您将输出作为输入传入。

    至于为什么会出现这种行为,可能是组件之间的一些奇怪的交互,也可能是未定义的。