Java

【OSにも使われている】スレッド

スレッドとは?

Javaのスレッド(thread)とは、プログラム上で複数の処理を同時に動かす仕組みです。

スレッドを利用する理由

JVMは、命令を1つずつ順番に実行します。つまり、ある命令を完全に実行し終えてから次の命令を実行します。複数のJVMがあればネットワーク通信をしながらキーボード入力したり同時に命令を実行できるようになります。そこで、JVMを複数に増やすためのスレッドという仕組みとAPIを用います。

スレッド(プロセス)の状態

New

プロセスが新しく作成された状態
スレッドのインスタンスが生成(new)された状態

Running

命令が実行されれいる

①より優先順位の高いスレッドがきたとき。「実行可能状態」に遷移します。

②wait()、sleep()メソッドが実行されたときや入出力等に伴う処理の遅延が発生したとき、その他、排他制御でロックされているとき「待機状態」に遷移します。

処理が完了したとき「終了」となります。

Waiting

プロセスは何らかのイベントの発生を待っている
例)プロセスは入力が終わるまで次の処理が行えないために入力が終わるまで待っている

Ready

プロセスはプロセッサに割り当てられるのを待っている状態。
スレッドが起動(start)された時この状態になります。JVMのスケジューラがスレッドの優先順位に基づいてスレッドを実行状態に遷移させていきます。

dead/Terminated

プロセスの実行が終了した

スレッドをどのように実装するか

・Thread class を継承する
・Runnable interface を実装する

の2つの方法があります。。。

2つの実装方法に共通したメソッドを以下に示します。

run()

スレッドで実行したい処理をこのrun()メソッドの中に記述します。

start()

ThreadまたはRunnableで実装したクラス型を用いてインスタンスを作成します。その作成したインスタンスのstart()メソッドを用いることでそのスレッドを作成できます。

class ThreadSample extends Thread {
    public void run() {
        System.out.println("スレッド" + getName() + "で動いてまーす");
    }
}

class ThreadExecutor {
    public static void main(String[] args) {
        ThreadSample t1 = new ThreadSample();
        ThreadSample t2 = new ThreadSample();
        ThreadSample t3 = new ThreadSample();
        t1.start();
        t2.start();
        t3.start();
    }
}

Thread classを継承する方法

public class PingPong extends Thread {
  private String word;
  private int delay;
  public PingPong(String whatToSay, int delayTime){
    word = whatToSay; 
    delay = delayTime;
  }

  public void run() { 
    try {
      for(;;) {
        System.out.print(word + “ “); 
        Thread.sleep(delay);
      }
    } catch (InterruptedException e) {
        return; }
      }

  public static void main(String[] args) {
    new PingPong(“ping”, 33).start();
    new PingPong(“PONG”,100).start();
  } 
}
Thread classの方法でスレッドの生成の仕方

class クラス名 extends Thread {
    public void run() {
        // スレッドの処理を記述します。
    }
}
Thread thread = new 上記クラス();
thread.start();

Runnable interfaceを実装する方法

public class RunPingPong implements Runnable { 
  private String word;
  private int delay;
  public PingPong(String whatToSay, int delayTime) {
    word = whatToSay; 
    delay = delayTime;
  }

  public void run() {
    try { 
      for(;;) {
        System.out.print(word + “ “);
        Thread.sleep(delay); 
      }
    } catch (InterruptedException e) {
        return;
      }
  }

  public static void main(String[] args) {
  Runnable ping = new RunPingPong(“ping”, 33); 
  Runnable pong = new RunPingPong(“PONG”, 100); 
  new Thread(ping).start();
  new Thread(pong).start();
  }
}
Runnable interfaceの方法でスレッドの生成の仕方

class クラス名 implements Runnable {
    public void run() {
        // スレッドの処理を記述します。
    }
}
Runnable runnable = new 上記クラス();
Thread thread = new Thread(runnable);
thread.start();

Thread classとRunnable interfaceの使いわけ

大きな違いはクラスかインターフェースかです。”Thread”がクラスなのに対し、”Runnable”はインターフェースなので、Threadは多重継承できないのに対し、Interfaceは幾つでもimplementできるのです。

そもそも、”Thread”クラスは”Runnable”を元にしているようなので、通常のスレッドプログラミングでは”Threadクラス”を、Threadの動きそのものを変更したい場合は”Runnable”インターフェースを書き換えることができます。

1 2 3