18083


Javaで毎分、0秒になったら処理を行いたいのですがどうすればいいのでしょうか?

下の例のように`while`を使う方法もありますが、getInstanceを何度も呼び出しているので、あまりいい方法ではないように思います。

Timerやscheduleを見ても、指定した秒数後に処理を実行することはできるようですが、指定秒になったら実行するようなものはありませんでした。

何か他にいい方法はあるのでしょうか?

[code]

    
    Calendar cal;
    while (true) {
        cal = Calendar.getInstance();
        if (cal.get(Calendar.SECOND) == 0) { // もし、calの秒が0秒なら
            // do something...
        }
    }
    
    
[/code]


CC BY-SA 3.0
2015-10-26T06:16:27.577
18082
2015-10-27T01:27:34.833
2015-10-26T06:32:54.673
5246
5246
question
java
Javaで毎分、0秒になったら処理を行う


Javaの標準機能であれば、`ScheduledExecutorService`というクラスがあります。  
このクラスを利用して下記のようなコードとした場合、60秒ごとにRunnableを継承したクラスの処理を実行することができます。

[code]

    ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    scheduler.scheduleAtFixedRate(Runnableを継承したクラス, 0, 60, TimeUnit.SECONDS);
    
[/code]

**2015/10/27追記**  
`ScheduledExecutorService`クラスを利用して指定秒に実行する方法ですが、  
例えば下記のコードのように、処理を繰り返すためのサービスと、繰り返し処理を起動ためのサービスの２つを定義し、繰り返し処理起動後に起動サービスを停止してしまえば、あとは指定秒に実行されるようになります。

[code]

    // 繰り返し処理用のサービス
    final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    // 繰り返し処理起動用のサービス
    final ScheduledExecutorService startScheduler = Executors.newScheduledThreadPool(1);
    // 繰り返し処理の内容
    final Runnable runner = () -> System.out.println(new Date());
    // 繰り返し処理の起動を行うためのRunnable
    final Runnable starter = () -> {
        final Calendar cal = Calendar.getInstance();
        if (0 == cal.get(Calendar.SECOND)) {
            scheduler.scheduleAtFixedRate(runner, 0, 60, TimeUnit.SECONDS);
            // 繰り返し処理が開始されたら起動サービスは停止
            startScheduler.shutdown();
        }
    };
    // 起動サービスをスタート
    startScheduler.scheduleAtFixedRate(starter, 0, 1, TimeUnit.SECONDS);
    
[/code]

このようにすることで、初回起動までは`Calendar.getInstance()`が複数回呼ばれてしまいますが、一度繰り返し処理起動した後は`Calendar.getInstance()`は呼ばれなくなります。


CC BY-SA 3.0
2015-10-26T06:38:12.010
18083
2015-10-27T01:27:34.833
2015-10-27T01:27:34.833
10724
10724
18082
answer


ライブラリには疎いので、自前で作るならこんな感じでしょうか。  
getInstance を呼ぶ頻度を減らしてみました。

[code]

    while (true) {
        Calendar cal = Calendar.getInstance();
        int sec = cal.get(Calendar.SECOND);
        if (sec == 0) {     // もし、calの秒が0秒なら
            System.out.println("do something");
            // 処理に1秒かからなかった場合の対処。
            Thread.sleep(1000);
        } else if (sec < 59) {
            Thread.sleep((59 - sec) * 1000);
        } else {
            // うるう秒対策込み
            Thread.sleep(1000);
        }
    }
    
[/code]


CC BY-SA 3.0
2015-10-26T13:36:11.710
18091
2015-10-26T13:36:11.710
5288
18082
answer