ScheduledExecutorService 的不稳定行为

发布于 2024-12-10 11:36:14 字数 1764 浏览 0 评论 0原文

我正在尝试在我正在开发的应用程序上使用 ScheduledExecutorService,但我遇到了不稳定的行为,并且无法弄清楚我是否做错了什么或者这是否是一些已知问题。 我已经尝试过文档中的示例:

class BeeperControl {

  private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);



  public void beepForAnHour() {

        final Runnable beeper = new Runnable() {

              public void run() {

                    System.out.println("beep");

              }

        };

        final ScheduledFuture<?> beeperHandle = scheduler.scheduleAtFixedRate(

                    beeper, 10, 10, TimeUnit.SECONDS);

        scheduler.schedule(new Runnable() {

              public void run() {

                    beeperHandle.cancel(true);

              }

        }, 60 * 60, TimeUnit.SECONDS);

  }



  public static void main(String[] args) {

        new BeeperControl().beepForAnHour();

  }

}

但这仅在 10 分钟内打印了 4 次值“beep”,而它应该每 10 秒打印一次。有人可以给我一些帮助吗?

亲切的问候,

Carlos Ferreira

编辑:

我已经在打印指令中添加了更多信息,并在两台不同的机器上运行了代码,一台使用 Windows XP,另一台使用 Unix,看看结果:

UNIX

在 Mon Oct 17 13:31:34 WEST 2011 发出

蜂鸣声 在 Mon Oct 17 13:31:44 WEST 2011

在 Mon Oct 17 发出蜂鸣声13:31:54 WEST 2011

蜂鸣声于 10 月 17 日星期一 13:32:04 WEST 2011

日星期一 13:32:14 WEST 2011

蜂鸣声于 10 月 17

蜂鸣声于 10 月 17 日星期一 13:32:24 WEST 2011蜂鸣声于 10 月 17 日星期一 13: 32:34 WEST 2011

Windows XP

在 10 月 17 日星期一 13:24:21 BST 发出

蜂鸣声 在 10 月 17 日星期一 13:25:54 BST 2011

蜂鸣声在 10 月 17 日星期一 13:27:08 BST 2011

在 10 月 17 日星期一 13:28 发出蜂鸣声: 03 BST 2011

于 10 月 17 日星期一 13:28:48 发出蜂鸣声BST 2011

蜂鸣声于 10 月 17 日星期一 13:29:40 BST 2011

蜂鸣声于 10 月 17 日星期一 13:30:31 BST 2011

I'm trying to use the ScheduledExecutorService on an application I'm developing, but I'm getting an erratic behavior and can't figure out if I'm doing something wrong or if this is some known issue.
I've tried the example on the documentation:

class BeeperControl {

  private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);



  public void beepForAnHour() {

        final Runnable beeper = new Runnable() {

              public void run() {

                    System.out.println("beep");

              }

        };

        final ScheduledFuture<?> beeperHandle = scheduler.scheduleAtFixedRate(

                    beeper, 10, 10, TimeUnit.SECONDS);

        scheduler.schedule(new Runnable() {

              public void run() {

                    beeperHandle.cancel(true);

              }

        }, 60 * 60, TimeUnit.SECONDS);

  }



  public static void main(String[] args) {

        new BeeperControl().beepForAnHour();

  }

}

But this only printed the value 'beep' 4 times in 10 minutes, when it should have printed it every 10 seconds. Can someone give me some help?

Kind regards,

Carlos Ferreira

EDIT:

I've added more info to the print instruction and ran the code on 2 different machines, one with Windows XP and another with Unix, look at the results:

UNIX

beep at Mon Oct 17 13:31:34 WEST 2011

beep at Mon Oct 17 13:31:44 WEST 2011

beep at Mon Oct 17 13:31:54 WEST 2011

beep at Mon Oct 17 13:32:04 WEST 2011

beep at Mon Oct 17 13:32:14 WEST 2011

beep at Mon Oct 17 13:32:24 WEST 2011

beep at Mon Oct 17 13:32:34 WEST 2011

Windows XP

beep at Mon Oct 17 13:24:21 BST 2011

beep at Mon Oct 17 13:25:54 BST 2011

beep at Mon Oct 17 13:27:08 BST 2011

beep at Mon Oct 17 13:28:03 BST 2011

beep at Mon Oct 17 13:28:48 BST 2011

beep at Mon Oct 17 13:29:40 BST 2011

beep at Mon Oct 17 13:30:31 BST 2011

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

物价感观 2024-12-17 11:36:14

本文是理解该问题的一个很好的起点。基本上,Windows 定时器有问题。 jdk ScheduledExecutorService 实现利用了 java 中基于“纳米时间”的 API,这是有问题的。我们必须更改代码,以便它在 Windows 上使用 java.util.Timer(它使用基于毫秒的 API,并且似乎在 Windows 上可靠地工作),并在其他地方使用 ScheduledExecutorService。

This article is a good starting point for understanding the problem. basically, windows timers have issues. The jdk ScheduledExecutorService implementation utilizes the "nano time" based APIs in java which are problematic. We had to change our code so that it utilizes java.util.Timer on windows (which uses the millisecond based APIs and seems to work reliably on windows) and the ScheduledExecutorService everywhere else.

单身狗的梦 2024-12-17 11:36:14

该代码工作得很好。由于以下原因,您可能会有另一种感觉:
1) API 说

创建并执行一个周期性操作,该操作首先在给定的初始延迟后启用,然后在给定的周期内启用;也就是说,执行将在initialDelay之后开始,然后是initialDelay+period,然后是initialDelay + 2 * period,依此类推。
这回答了该行为。

2)
`scheduler.schedule(new Runnable() {

          public void run() {

                beeperHandle.cancel(true);

          }

    }, 60*60, TimeUnit.SECONDS);

即 1 小时。因此大约一个小时,它将显示输出。
3)即使将时间从60*60更改为10,仍然不会终止。因为 shutdown 永远不会被调用。

scheduler.schedule(new Runnable() {

          public void run() {
                beeperHandle.cancel(true);
                scheduler.shutdown();
          }

    }, 10, TimeUnit.SECONDS);

现在它将正确终止

The code works perfectly fine. You might be feeling the other way due to:
1) The API says

Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with the given period; that is executions will commence after initialDelay then initialDelay+period, then initialDelay + 2 * period, and so on.
This answers the behaviour.

2)
`scheduler.schedule(new Runnable() {

          public void run() {

                beeperHandle.cancel(true);

          }

    }, 60*60, TimeUnit.SECONDS);

ie for 1 hour. Hence for about an hour it will display the output.
3) Even though if you change the time from 60*60 to 10, still it wont terminate. Because shutdown is never called.

scheduler.schedule(new Runnable() {

          public void run() {
                beeperHandle.cancel(true);
                scheduler.shutdown();
          }

    }, 10, TimeUnit.SECONDS);

Now it will terminate properly

南风起 2024-12-17 11:36:14

看看这篇文章。它讨论了一个非常相似的问题。这可能有助于找出真正的问题。

Hava a look at this article. It discusses a very similar problem. This might help in figuring out the real problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文