ScheduledExecutorService的不稳定行为

时间:2011-10-17 12:00:19

标签: java multithreading

我正在尝试在我正在开发的应用程序上使用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次“哔”值,此时它应该每10秒打印一次。有人可以给我一些帮助吗?

亲切的问候,

Carlos Ferreira

修改

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

UNIX

在10月17日星期一13:31:34 2011年西部发出哔哔声

在10月17日星期一13:31:44西2011年发出哔哔声

在10月17日星期一13:31:54西2011年发出哔哔声

在10月17日星期一13:32:04 2011年西部发出哔哔声

在10月17日星期一13:32:14 2011年西部发出哔哔声

在10月17日星期一13:32:24西2011年发出哔哔声

在10月17日星期一13:32:34 2011年西部发出哔哔声

Windows XP

在2011年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发出哔哔声

2011年10月17日星期一13:29:40发出哔哔声

2011年10月17日星期一13:30:31 BST发出哔哔声

3 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:1)

代码完美无缺。你可能会感觉到另一种方式: 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);

现在它将正常终止

答案 2 :(得分:0)

Hava看看这个article。它讨论了一个非常类似的问题。这可能有助于弄清楚真正的问题。