0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ScheduledThreadPoolExecutorとTimerによるタイマーの実装の違い

Posted at

Timerの実装

java.util.Timer

でタイマーを実装することができますが、ほかにも

java.util.concurrent.Executors;
java.util.concurrent.ScheduledExecutorService;

を使って実装することも可能です。

記事の目的

タイマーで次のように10ms間隔でタスクを定期実行するよう設定した場合、

TimerTest.java
import java.util.Timer;

public class TimerTest {

    public static void main(String[] args) {
        // Timerクラスのオブジェクトを作成
        Timer time = new Timer();
        time.scheduleAtFixedRate(new SampleTask(), 0, 10);
    }
}
SampleTask.java
import java.util.TimerTask;

public class SampleTask extends TimerTask {
    public long before_time;

    public void run() {
        long now_time = System.currentTimeMillis();
        System.out.print("interval time[ms] ");
        System.out.println(now_time - before_time);
        before_time = now_time;
    }
}

結果

interval time[ms] 15
interval time[ms] 16
interval time[ms] 0
interval time[ms] 16
interval time[ms] 15
interval time[ms] 0
interval time[ms] 16
interval time[ms] 16
interval time[ms] 0
interval time[ms] 16
interval time[ms] 0
interval time[ms] 16
interval time[ms] 16
interval time[ms] 0
interval time[ms] 16
interval time[ms] 16
interval time[ms] 0
interval time[ms] 15
interval time[ms] 0
interval time[ms] 16
interval time[ms] 16
interval time[ms] 0
interval time[ms] 15
interval time[ms] 15
interval time[ms] 0
interval time[ms] 15

インターバル間隔は15msや0msなど不安定です
ここが、大きな問題です。

ちなみに

Timer.scheduleAtFixedRate

でタスクを設定した場合、タスクがインターバル間隔以上に時間がかかったりすると、すぐ実行してしまったりします。

こちらの方の説明が非常にわかりやすいです。

Executor.scheduleWithFixedDelay

を使用すれば固定間隔で使用できます。

ScheduledExecutorService: サンプルコード

ScheduleThread.java
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledThread {

    public static void main(String[] args){

        ScheduledExecutorService executor = Executors.newScheduledThreadPool(15);
        ScheduledWork work1 = new ScheduledWork();

        //executor.scheduleAtFixedRate(work1, 0,1, TimeUnit.MILLISECONDS);
        executor.scheduleWithFixedDelay(work1, 0,100, TimeUnit.MICROSECONDS);
    }

}
ScheduledWork.java
public class ScheduledWork implements Runnable{

    public long before_time;

    @Override
    public void run(){
        long now_time = System.currentTimeMillis();
        System.out.println(now_time - before_time);
        before_time = now_time;

    }

}

コードの説明

定期実行するインスタンスはインターフェースRunnnableを継承します。Runnnableはrunメソッドを持つクラスのことです。
Executerとは

この中で、

newScheduledThreadPool

の説明は

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
指定された遅延時間後、または周期的にコマンドの実行をスケジュールできる、スレッド・プールを作成します。
パラメータ:
corePoolSize - アイドルであってもプール内に維持されるスレッドの数。
戻り値:
新規生成されたスケジュール済みのスレッド・プール
例外:
IllegalArgumentException - corePoolSize < 0の場合

こちらとなります。
私の理解では、タスク=Executorです

こちらも参考になります。

サンプルコードと結果について

WithFixedDelayで100usで設定した場合、

interval time[ms] 16
interval time[ms] 16
interval time[ms] 0
interval time[ms] 15
interval time[ms] 17
interval time[ms] 15
interval time[ms] 0
interval time[ms] 0
interval time[ms] 16
interval time[ms] 15
interval time[ms] 15
interval time[ms] 16
interval time[ms] 15
interval time[ms] 16
interval time[ms] 15
interval time[ms] 16
interval time[ms] 15
interval time[ms] 15
interval time[ms] 16
interval time[ms] 16
interval time[ms] 16
interval time[ms] 16
interval time[ms] 16
interval time[ms] 16
interval time[ms] 15
interval time[ms] 15
interval time[ms] 16
interval time[ms] 16
interval time[ms] 15
interval time[ms] 15
interval time[ms] 16
interval time[ms] 16
interval time[ms] 15
interval time[ms] 16
interval time[ms] 15
interval time[ms] 16
interval time[ms] 15
interval time[ms] 15
interval time[ms] 1
interval time[ms] 15
interval time[ms] 0
interval time[ms] 16
interval time[ms] 16
interval time[ms] 15
interval time[ms] 16
interval time[ms] 15
interval time[ms] 16
interval time[ms] 16
interval time[ms] 16

こんな感じで結局15msほどで反復実行します。
また、0msなどもあり不安定です。

intervalを30msにすると

interval time[ms] 32
interval time[ms] 31
interval time[ms] 31
interval time[ms] 31
interval time[ms] 31
interval time[ms] 31
interval time[ms] 31
interval time[ms] 30
interval time[ms] 33
interval time[ms] 31
interval time[ms] 32
interval time[ms] 31
interval time[ms] 32
interval time[ms] 32
interval time[ms] 30
interval time[ms] 32
interval time[ms] 31
interval time[ms] 31
interval time[ms] 31
interval time[ms] 31
interval time[ms] 31
interval time[ms] 31
interval time[ms] 32
interval time[ms] 31
interval time[ms] 30
interval time[ms] 31
interval time[ms] 45
interval time[ms] 46
interval time[ms] 45
interval time[ms] 30
interval time[ms] 31
interval time[ms] 31
interval time[ms] 32
interval time[ms] 30
interval time[ms] 46
interval time[ms] 31
interval time[ms] 46
interval time[ms] 31
interval time[ms] 30
interval time[ms] 31
interval time[ms] 31
interval time[ms] 31

30~46msとこれでも微妙に遅かったりちょうどよかったりします。

まとめ

TimerもScheduledExecutorServiceどちらで実装しても、差はありません。
インターバル間隔がms単位の場合、15ms単位の遅れが突如混ざる可能性はどちらでもありえます。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?