【Java入門】Threadをsleepメソッドで一定時間停止する方法

こんにちは!フリーライターの中井です。

Javaにはスレッドの処理を一時停止させるsleepメソッドがあります。この記事では、

  • スレッドとは?
  • sleepメソッドとは?
  • sleepメソッドの使い方
  • という基本的な内容から、

  • スリープ中に割り込まれると例外が発生すること
  • sleepメソッドは誤差が出ること
  • などの応用的な使い方に関しても解説していきます。

    スレッド(Thread)とは

    スレッドとは、処理の実行単位の一つで、プログラムの初めから終わりまでの一連の流れのことを言います。

    専門的な言い方になりますが、実はHello,Worldを出力するプログラムも一連のスレッドになります。

    更にスレッドは、シングルスレッドとマルチスレッドの2種類に分かれます。

    シングルスレッドとは?

    シングルスレッドは、別名直列処理とも呼ばれています。

    例えば、夏休みの宿題に英語の問題集と数学の問題集があるとします。
    シングルスレッドの場合は英語の問題集をスタートさせて、終わってから数学の問題集をスタートします。

    覚え方としては、初めの処理が終わってから次の処理をすると理解しておきましょう。

    つまり、プログラムの始まりから終わりまでが一本道で処理されるのがシングルスレッドとなります。

    マルチスレッドとは?

    一方マルチスレッドは、別名並行処理とも呼ばれています。シングルスレッドと同じように夏休みの宿題で例えると、マルチスレッドの場合は英語の問題集と数学の問題集に同時に取り組みます。

    覚え方としては、2つ以上の処理を並行して行うと理解しておきましょう。マルチスレッドを利用するには、

  • 1. Threadクラスを継承するクラスを作成する
  • 2. Threadクラスを継承するクラスでrunメソッドを実行する
  • 3. Threadクラスを継承するクラスのインスタンスを生成する
  • 4. 生成したインスタンスに対してstartメソッドを実行する
  • となります。以下にマルチスレッドを実行する簡単なサンプルを紹介します。

    public class ThreadSample {
    
        public static void main(String[] args) {
        	 
            MultiThread1 mt1 = new MultiThread1();
            MultiThread2 mt2 = new MultiThread2();
            mt1.start();
            mt2.start();
        }
    }
    
    class MultiThread1 extends Thread {
        public void run() {
            for (int i = 0; i < 3; i++) {
    
            	System.out.println("スレッド1 : " + (i + 1) + "回目");
    
            }
        }
    }
    
    class MultiThread2 extends Thread {
        public void run() {
            for (int i = 0; i < 3; i++) {
    
            	System.out.println("スレッド2 : " + (i + 1) + "回目");
    
            }
        }
    }
    
    

    実行結果

    スレッド2 : 1回目
    スレッド1 : 1回目
    スレッド2 : 2回目
    スレッド1 : 2回目
    スレッド2 : 3回目
    スレッド1 : 3回目
    

    サンプルプログラムでは、マルチスレッドを行うためにThreadクラスを継承したMultiThread1クラスとMultiThread2クラスを作成し、mainメソッドからstartメソッドでスレッドを実行しています。

    実行結果から分かるとおり、スレッドによる並行処理が実施されていることがわかりますね!

    sleepメソッドとは

    sleepメソッドとは、プログラムを一時停止するときに使用します。

    とくにマルチスレッドで使用することが多いメソッドです。sleepメソッドの定義は以下のようになっています。

    public static void sleep(long millis)
    

    sleepメソッドを使用するメリットとして、マルチスレッドの並列処理で無限ループを実行していた場合、CPUの負荷が大きくなりリソースを消費してメモリリークなどPCの動作が重くなる要因となってしまいます。

    そのため、マルチスレッドの処理中にsleepメソッドを使用して、処理を一時停止すればCPUの負荷を抑えられることができます。

    sleepメソッドの使い方

    ここでは実際にsleepメソッドの使い方を見ていきましょう。

    以下にsleepメソッドを使用した簡単なサンプルを記述します。

    public class JavaSleep {  
         public static void main(String[] args) {
            try {
                System.out.println("5秒停止します");
                Thread.sleep(5000);
                System.out.println("一時停止を解除しました。");
            } catch(InterruptedException e){
                e.printStackTrace();
            }      
        }    
    }
    

    実行結果

    5秒停止します
    一時停止を解除しました。
    

    このプログラムではsleepメソッドを使って、処理を5秒間停止させています。例外にはtry-catch文で対処しています。

    sleepメソッドのポイントは以下の2つです。

  • sleepメソッドの引数はlong型を使用、単位はミリ秒(1000ミリ秒 = 1秒)
  • sleepメソッドを使う場合には必ず例外処理をすること
  • マルチスレッドでsleepを実行

    ここでは、マルチスレッドの並行処理でsleepメソッドを使用する方法を紹介しています。

    実際のシステムでも、以下のサンプルのようにマルチスレッドでsleepメソッドを使用する機会は多いので、ぜひ覚えておきましょう。

    public class ThreadSample {
    
        public static void main(String[] args) {
        	 
            MultiThread1 mt1 = new MultiThread1();
            MultiThread2 mt2 = new MultiThread2();
            mt1.start();
            mt2.start();
        }
    }
    
    class MultiThread1 extends Thread {
        public void run() {
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(1000);
                    System.out.println("スレッド1 : " + (i + 1) + "回目");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    class MultiThread2 extends Thread {
        public void run() {
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(1000);
                    System.out.println("スレッド2 : " + (i + 1) + "回目");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    

    実行結果

    スレッド1 : 1回目
    スレッド2 : 1回目
    スレッド1 : 2回目
    スレッド2 : 2回目
    スレッド1 : 3回目
    スレッド2 : 3回目
    スレッド1 : 4回目
    スレッド2 : 4回目
    スレッド1 : 5回目
    スレッド2 : 5回目
    

    サンプルではThreadクラスを継承したMultiThread1クラスとMultiThread2クラスでrun()メソッドでスレッドを実行し、for文の中でsleepメソッドを使用しています。

    sleepメソッドの注意点

    sleepメソッドの注意点は、以下の2つです。

  • interruptedExceptionの例外が発生すること
  • sleepメソッドでは精度が低く誤差が生じること
  • interruptedExceptionの例外に対処する方法

    interruptedExceptionの例外は、sleepメソッドで待機中にinterruptメソッドで割り込みが発生したときに発生します。

    必要に応じて例外に対処するプログラムを書いてください。interruptedExceptionの例外に対処する方法を覚えるために、次のソースコードで確認してみましょう。

    public class JavaSleep extends Thread{  
        public void run(){
            try {
                System.out.println("runメソッド:1秒停止します");
                Thread.sleep(1000);
            } catch(InterruptedException e){
                System.out.println("プログラムの割り込みが発生しました");           
                e.printStackTrace();
                
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
            JavaSleep js = new JavaSleep();     
            js.start();
            Thread.sleep(500);  
            js.interrupt();
        }
        
    }
    

    実行結果

    runメソッド:1秒停止します
    プログラムの割り込みが発生しました
    java.lang.InterruptedException: sleep interrupted
    	at java.lang.Thread.sleep(Native Method)
    	at javasleep.JavaSleep.run(JavaSleep.java:11)
    
    

    まずこのプログラムはrunメソッドが待機状態になるのを待つために500ミリ秒待機します。

    その後interruptメソッドで待機中のrunメソッドに割り込み、interruptedExceptionの例外を発生させています。

    sleepメソッドで誤差が発生する問題

    sleepメソッドはプログラムを実行する環境によっては誤差が発生する場合があります。

    そのため、高い精度が必要な処理では使わないようにしてください。次のプログラムで誤差を計測してみましょう。

    public class JavaSleep {  
        public static void main(String[] args) {
            try {
                for (int i = 0; i < 5; i++) {
                    long start = System.currentTimeMillis();
                    Thread.sleep(1000);
                    long stop = System.currentTimeMillis();
                    System.out.println((stop - start) + " [ms]");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    

    実行結果

    1001 [ms]
    1000 [ms]
    1001 [ms]
    1000 [ms]
    1000 [ms]
    

    プログラムの実行結果から、sleepメソッドで誤差が発生することを確認できました。

    Threadクラスについてもっと知りたい方へ

    紹介したようにThreadクラスを使用すれば、同時並行で処理を実行することが可能です。

    実際のシステムでマルチスレッドを使用したプログラムは多いので、仕組みはぜひ覚えておきましょう。

    この記事では紹介しきれなかったThreadクラスのいろいろな使い方を次の記事にまとめているので、ぜひ確認してください!

    まとめ

    この記事ではsleepメソッドの使い方について解説しました。

    sleepメソッドで待機中にinterruptメソッドで割り込みを行うと、interruptedExceptionの例外が発生するので注意してくださいね。

    もし、sleepメソッドの使い方を忘れてしまったらこの記事を確認してくださいね!

    LINEで送る
    Pocket

    「プログラミング、右も左もわからない…」という方にオススメ

    当プログラミングスクール「侍エンジニア塾」では、これまで6000人以上のエンジニアを輩出してきました。

    その経験を通してプログラミング学習に成功する人は、「目的目標が明確でそれに合わせた学習プランがあること」「常に相談できる人がそばにいること」「自己解決能力が身につくこと」この3つが根付いている傾向を発見しました。

    侍エンジニア塾は上記3つの成功ポイントを満たすようなサービス設計に磨きをかけております。

    cta_under_bnr

    「自分のスタイルや目的に合わせて学習を進めたいな」とお考えの方は、ぜひチェックしてみてください。

    書いた人

    中井

    中井

    フリーライター。
    主に美容系、ライフスタイル系含めこれまでに500本以上執筆。
    趣味はオンラインゲームにフリーソフトの情報収集。

    プログラミンとの出会い
    -----------------------------------------------------------------------------------------
    PCとプログラミングは大学からです。
    それまでは、PCは触ると壊れると思い込んでました。

    大学の授業で面白そうな理由でJavaを専攻。
    全然授業についていけず、後ろの席の子に課題をやってもらってました。

    そんなプログラミング音痴な状態で社会人を迎え、先輩からVBAがオススメと言われVBAを職場の人から教えてもらい習得。
    その後、自分の業務に携わるものおは全てVBAを組みました。

    会社を退職後、再度Javaを勉強する機会に恵まれ、大学でわからなかったことが一気に理解できるように。
    念願のAndroidアプリでTwitterのクライアントアプリを作れるまでになりました。
    以後、文章の修行の傍らJavaの最新情報を追う日々が続いています。