トップ 差分 一覧 ping ソース 検索 ヘルプ PDF RSS ログイン

SJC-P 並行性


RSS 無料英単語

目次



記事一覧

キーワード

SJC-P 並行性

 スレッド

  • 各スレッドには優先順位
  • 新しい実行のスレッドを作成するには 2 通りの方法
    • クラスを Thread のサブクラスであると宣言
    • Runnable インタフェースを実装するクラスを宣言

  • Runnable実装クラスの、run()メソッドを直接呼ばない(単なるメソッドの呼び出しとなり、スレッドは開始されない)。Thread.start()を利用する。

関連メソッド
method 内容
getPriority() 優先順位を返す
setPriority(int newPriority) 優先順位を変更
getState() 状態を返す
interrupt() このスレッドに割り込み
interrupted() 現在のスレッドが割り込まれているかどうか
isInterrupted() このスレッドが割り込まれているどうか
isAlive() このスレッドが生存しているかどうか
isDaemon() このスレッドがデーモンスレッドであるかどうか
setDaemon(boolean on) デーモンスレッドまたはユーザースレッドとしてマーク
join() このスレッドが終了するのを待機
sleep(long millis) 現在実行中のスレッドを、指定されたミリ秒数の間、スリープ
start() スレッドの実行を開始
yield() 現在実行中のスレッドオブジェクトを一時的に休止させ、ほかのスレッドが実行できるように
notify() このオブジェクトのモニターで待機中のスレッドを 1 つ再開
notifyAll() このオブジェクトのモニターで待機中のすべてのスレッドを再開
wait() ほかのスレッドがこのオブジェクトの notify() メソッドまたは notifyAll() メソッドを呼び出すまで、現在のスレッドを待機

import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

@SuppressWarnings("serial")
public class ThreadTest extends JFrame {
  private JTextField txt1;
  private JTextField txt2;
  public ThreadTest() {
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    txt1 = new JTextField();
    txt2 = new JTextField();
    this.getContentPane().add(txt1, BorderLayout.CENTER);
    this.getContentPane().add(txt2, BorderLayout.SOUTH);

    // 非同期でテキストフィールドの内容をカウントアップするスレッドを作成
    Thread t = new Thread(
        // Threadコンストラクタの引数にRunnableインターフェースの実装クラスを渡す
        new Runnable() {
          public void run() {
            int i = 0;
            while (true) {
              txt2.setText(String.valueOf(i++));
              try { Thread.sleep(500); } 
              catch (InterruptedException e) {}
            }
          }
        }
    );
    // 開始(Thred.start()を呼ぶ)
    t.start();

    this.pack();
    this.setVisible(true);
  }
  public static void main(String[] args) throws Exception {
    SwingUtilities.invokeAndWait(
      new Runnable() {
        public void run() {
          new ThreadTest();
        }
      }
    );
  }
}

 標準入力を待つスレッドと、入力された値をエコーするスレッドを、wait,notifyAll で協調動作させる。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;

public class ConcurrentTest4 {
    Queue<String> queu = new LinkedList<String>();

    public static void main(String[] args) {
        ConcurrentTest4 me = new ConcurrentTest4();
        new Thread(me.new InputProcess()).start();
        new Thread(me.new OutputProcess()).start();
    }

    private class InputProcess implements Runnable {
        public void run() {
            // 共有オブジェクト(モニター)を同期指定
            synchronized (queu) {
                try { 
                    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
                    System.out.print("input message >");
                    String line = null;
                    while ((line = reader.readLine()) != null) {
                        queu.offer(line); // キューに挿入
                        // 準備が終わったので、OutputProcessに通知し、自身はwaitする
                        queu.notifyAll();
                        System.out.println("[in]waiting...");
                        queu.wait(); // waitを呼び出すとき、現在のスレッドは、このオブジェクトモニターのオーナでなければならない。
                    }
                } catch (IOException ioe) { ioe.printStackTrace(); }
                  catch (InterruptedException ipe) { ipe.printStackTrace(); }
            }
        }
    }
    private class OutputProcess implements Runnable {
        public void run() {
            synchronized (queu) {
                while (true) {
                    try {
                        if (queu.size() > 0) {
                            System.out.println("echo >" + queu.poll());
                            // 処理が終わったので、InputProcess に通知し、自身はwait
                            queu.notifyAll();
                        }
                        System.out.println("[out]waiting...");
                        queu.wait();
                    } catch (InterruptedException e) { e.printStackTrace(); }
                }
            }
        }
    }
}


public class ConcurrentTest1 {
   public static void main(String[] args) {
        ConcurrentTest1 ct1 = new ConcurrentTest1();
        new Thread(ct1.new T1()).start();
        new Thread(ct1.new T2()).start();
    }
    private class T1 implements Runnable {
        public void run() {
            for (int i=0;i<5;i++) {
                // こういうロックも取得できる
                // 標準出力への割り込みをブロックし、START-ENDが対になるように制御   
                synchronized (System.out) {   
                    System.out.println("T1(" + i + ") START");
                    try { Thread.sleep(1000); } 
                    catch (InterruptedException e){ e.printStackTrace(); }
                    System.out.println("T1(" + i + ") END");
                }
            }
            
        }
    }
    private class T2 implements Runnable {
        public void run() {
            for (int i=0;i<5;i++) {
                synchronized (System.out) {
                    System.out.println("T2(" + i + ") START");
                    try { Thread.sleep(500); } 
                    catch (InterruptedException e){ e.printStackTrace(); }
                    System.out.println("T2(" + i + ") END");
                }
            }
        }
    }
}

結果

T1(0) START
T1(0) END
T2(0) START
T2(0) END
T1(1) START
T1(1) END
T2(1) START
T2(1) END
T1(2) START
T1(2) END
T2(2) START
T2(2) END
T1(3) START
T1(3) END
  :

synchronized がないと、T1、T2のSTART-ENDの間に割り込こみが起こる。



YAGI Hiroto (piroto@a-net.email.ne.jp)
twitter http://twitter.com/pppiroto

Copyright© 矢木 浩人 All Rights Reserved.