java-beginner.com ブログ

プログラミングを学習するブログ(Javaをメインに)

スレッドをスリープさせる

投稿日:

最終更新日:2016年09月11日

アイキャッチ

こんにちは。「Javaを復習する初心者」です。

今回はスレッドをスリープさせる方法を使ってみました。

スレッドをスリープさせる方法を調べた結果、2つあるのが分かりました。Thread#sleep()メソッド、TimeUnit#sleep()メソッドです。以下ではそれぞれを使ってみます。

Thread#sleep()

スレッドをスリープさせる方法は一つ目はThread#sleep()メソッドを使うことです。引数にはミリ秒を指定します。例えば、以下のプログラムではスレッド内で5秒スリープしています。

ソース

        Thread t1 = new Thread(() -> {
            long start, end;
            start = System.currentTimeMillis();
            try {
                Thread.sleep(500);
            } catch (Exception e) {
                e.printStackTrace();
            }
            end = System.currentTimeMillis();
            System.out.println(end -start);
        });

        t1.start();

実効結果は以下です。

結果

500

System#currentTimeMillis()メソッドを使うとミリ秒で表される現在の時間を取得できます。開始と終了の差を出力しています。上記のように500ミリ秒と出力されました。スレッドが5秒スリープしたということです。

TimeUnit#sleep()

スレッドをスリープさせる別の方法はTimeUnit列挙型sleep()メソッドを使うことです。このメソッドはstaticではありません。なのでTimeUnitの定数を使う必要があるようです。

TimeUnitには以下の定数が定義されています。全て時間単位を表します。

定数 時間単位
DAYS 24時間
HOURS 60分
MICROSECONDS ミリ秒の1000分の1
MILLISECONDS 秒の1000分の1
MINUTES 60秒
NANOSECONDS マイクロ秒の1000分の1
SECONDS 1秒

以下、TimeUnit.SECONDSを使い、sleep()メソッドを呼び出してみました。

ソース

        Thread t1 = new Thread(() -> {
            long start, end;
            start = System.currentTimeMillis();
            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (Exception e) {
                e.printStackTrace();
            }
            end = System.currentTimeMillis();
            System.out.println(end -start);
        });

        t1.start();

結果

10001

上記の通り、約10秒となりました。

TimeUnit#sleep()メソッドについて、API仕様書には「Thread.sleepを実行します」と書いてあります。ソースを見ると確かに「Thread.sleep(ms, ns);」という行がありました。Thread.sleepはInterruptedExceptionをスロー宣言しているメソッドですが、try-catch文はありませんでした。その代わり、TimeUnit#sleep()メソッドにInterruptedExceptionのスロー宣言がありました。そのため、上記のプログラムではtry-catch文を書いています。

「Thread.sleep(ms, ns);」についてですが、第一引数に負の数が指定されてた場合、IllegalArgumentExceptionがすろーされるようになってます。TimeUnit#sleep()側ではif文を使っていて、引数がゼロまたはそれより小さい場合はスリープしないようになっています。

TimeUnit#sleep()メソッドの内部ではtoMillis()メソッドが呼び出されます。TimeUnit.SECONDSに対して、sleepメソッドを呼び出した場合、SECONDS.toMillis()が呼び出される仕組みです。ソースを追ってみると、NANOSECONDS~DAYSまでtoMillisメソッドの定義が書いてある箇所があります。それぞれ、static long x(long d, long m, long over)というメソッドを呼び出しているのですが、引数を調節して、統一的に変換できるように記述されてました。