モーダルを閉じる工作HardwareHub ロゴ画像

工作HardwareHubは、ロボット工作や電子工作に関する情報やモノが行き交うコミュニティサイトです。さらに詳しく

利用規約プライバシーポリシー に同意したうえでログインしてください。

工作HardwareHub ロゴ画像 (Laptop端末利用時)
工作HardwareHub ロゴ画像 (Mobile端末利用時)

マルチスレッドプログラミングの簡単な例 (Java)

モーダルを閉じる

ステッカーを選択してください

モーダルを閉じる

お支払い内容をご確認ください

購入商品
」ステッカーの表示権
メッセージ
料金
(税込)
決済方法
GooglePayマーク
決済プラットフォーム
確認事項

利用規約をご確認のうえお支払いください

※カード情報はGoogleアカウント内に保存されます。本サイトやStripeには保存されません

※記事の執筆者は購入者のユーザー名を知ることができます

※購入後のキャンセルはできません

公開日公開日
2013/08/15
最終更新最終更新
2018/10/07
記事区分記事区分
一般公開

目次

    アカウント プロフィール画像 (サイドバー)

    どもです

    0
    ステッカーを贈るとは?

    あるプロセス内で複数の独立した処理を実行するためには、そのプロセス内に複数個のスレッドを用意します。それらのスレッドは、OSからプロセスに割り当てられたリソース (メモリやCPU実行時間) を共有しつつ、独立した処理を進めます。具体的な実装方法には、Threadを継承する方法とRunnableインターフェースを実装する方法の二つがあります。以下の例ではThreadを継承する方法を採用しています。なお、Threadはjava.langパッケージに属しているため、importせずに使用できます。

    sample.java

    class MyThread extends Thread {
        private int sleepTime;
        public MyThread(int sleepTime) {this.sleepTime=sleepTime;}
        public void run() { //runを実装して具体的な処理を記述
            try {
                for(int i=0; i<5; ++i) {
                    Thread.sleep(sleepTime);
                    System.out.println(sleepTime);
                }
            }
            catch(InterruptedException ex) { //sleep中に発生しうる例外
                ex.printStackTrace(); //InterruptedExceptionを捕獲できるようにする必要有
            }
        }
    }
    
    class Sample {
        public static void main(String args[]) {
            MyThread t1 = new MyThread(1000);
            MyThread t2 = new MyThread(2000);
            t1.start();
            t2.start();
            try {
                t1.join(); //t1のrunが完了するまで待機
                t2.join(); //t2のrunが完了するまで待機
                System.out.println("Both t1 and t2 finished.");
            }
            catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    実行例

    $ javac sample.java && java Sample 
    1000
    2000
    1000
    1000
    2000
    1000
    1000
    2000
    2000
    2000
    Both t1 and t2 finished.
    

    共通リソースを連携して処理

    先程のサンプルでは、完全に独立した処理を各スレッドが実行していました。今回は、共通のオブジェクトの参照を各スレッドに渡して連携して処理してもらいます。その際、リソースのメソッドにsynchronizedを修飾子として指定し、片方がリソースを使用している間はロックをかけ他方が利用できないようにします。リソースを使用する予定だが他方が終了してから使用したい場合は、wait()を呼びだして一時的にロックを解除します。また、リソースを使用し終わったスレッドはnotifyAll()でwait中の別のスレッドにその旨を連絡します。共通リソースを連携して処理するため、synchronizedを用いたマルチスレッドプログラミングを行うと、意図せずデッドロックが発生する危険性あることにも注意しましょう。

    sample.java

    class MyThread extends Thread {
        private MyArr myArr;
        private String name;
        public MyThread(String name, MyArr myArr) {
            this.name = name;
            this.myArr = myArr;
        }
        public void run() {while(myArr.add(name));}
    }
    
    class MyArr {
        private static final int SIZE=8;
        private String arr[];
        private int idx;
        public MyArr() {
            this.arr = new String[SIZE];
            this.idx = 0;
        }
        public synchronized boolean add(String name) {
            if(idx==SIZE) return false;
            while(name.equals("odd") && idx%2==0
                  || name.equals("even") && idx%2==1) {
                try {
                    wait(); //ロックを解除し、notifyされるまで待機
                }
                catch(InterruptedException e){
                    e.printStackTrace();
                    System.exit(0);
                }
            }
            if(idx==SIZE) return false;
            arr[idx++]=name;
            notifyAll(); //wait中の別スレッドに間もなく処理が完了することを連絡
            return true;
        }
        public void display() {for(int i=0; i<SIZE; ++i) System.out.println(arr[i]);}
    }
    
    class Sample {
        public static void main(String args[]) {
            MyArr myArr = new MyArr();
            MyThread t1 = new MyThread("odd", myArr);
            MyThread t2 = new MyThread("even", myArr);
            t1.start();
            t2.start();
            try {
                t1.join();
                t2.join();
                myArr.display();
            }
            catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    実行例

    $ javac sample.java && java Sample 
    even
    odd
    even
    odd
    even
    odd
    even
    odd
    
    0
    詳細設定を開く/閉じる
    アカウント プロフィール画像 (本文下)

    どもです

    記事の執筆者にステッカーを贈る

    有益な情報に対するお礼として、またはコメント欄における質問への返答に対するお礼として、 記事の読者は、執筆者に有料のステッカーを贈ることができます。

    さらに詳しく →
    ステッカーを贈る コンセプト画像

    Feedbacks

    Feedbacks コンセプト画像

      ログインするとコメントを投稿できます。

      関連記事

      • Spring Security フォームログインのサンプルコード
        Spring フレームワークによる Web アプリケーション開発で、ログイン処理を実装する際は Spring Security が便利です。ここでは特に Spring Boot で Web アプリケーションを開発する場合を対象とし、フォームによる ID/Password ログインを行うためのサンプルコードをまとめます。 公式ドキュメント [Spring Security チュートリアル](http...
        えびちゃんえびちゃん12/4/2019に更新
        いいねアイコン画像0
      • Java配列の宣言方法 (C/C++との違い)
        Javaの配列 Javaの配列宣言方法はC/C++と似ているようで若干異なる。 初期化しない場合 C/C++の int array[10]; はJavaでは int array[] = new int[10]; となる。同様にC/C++の int array[3][3]; はJavaでは int array[][] = new int[3][3]; となる。 初期化
        てんとうむしてんとうむし5/13/2018に更新
        いいねアイコン画像0
      • PlantUML による UML 図の描き方
        サムネイル画像-c788fffde5
        PlantUML はテキスト形式で表現されたシーケンス図やクラス図といった UML (Unified Modeling Language) 図の情報から画像を生成するためのツールです。簡単な使い方をまとめます。 インストール方法の選択 Atom や Eclipse のプラグインをインストールしてエディタから利用する方法、JAR をダウンロードして Java コマンドで実行する方法、Redmine ...
        kentakenta1/21/2020に更新
        いいねアイコン画像0
      • Akka HTTP サンプルコード (Scala)
        サムネイル画像-a98142497c
        Akka アクターを用いて実装された汎用 HTTP フレームワークです。Spray の後継です。コアモジュールである akka-http-core は 2016/2/17 に experimental が外れました。akka-http などのいくつかのサブモジュールは 2016/3/1 現在 experimental のままですが、基本的な
        雄太雄太10/7/2021に更新
        いいねアイコン画像0
      • Kestrel の使用例
        Kestrel は Message Queue (MQ) の実装のひとつです。一般に MQ はアプリケーション間やプロセス間、スレッド間で非同期に通信するために用いられます。メッセージの送信側は MQ に書き込めば受信側の応答を待たずに次の処理に非同期に進むことができます。Kestrel はわずか 2500 行程の Scala で実装されており JVM で動作します。MQ 自体はメモリ上に存在する...
        したくんしたくん10/12/2017に更新
        いいねアイコン画像0