LoginSignup
24
29

More than 5 years have passed since last update.

ざっくりJava〜スレッド〜

Last updated at Posted at 2014-02-05

書いてる人

プログラミング学習サービスやら、ペットサロン予約サービス、風俗検索サービスなど色々とやっている「かずきち」です。
■運営サービス一部
http://crazy-wp.com/
http://webukatu.com/
新宿のホストから不動産・保険の営業を経て、HTMLって何?という状態から3ヶ月独学でプログラミングやデザインを学び、IT業界で1年間実務経験を積んで年収は1本超え。現在は起業家としてサービス運営やら不動産運営をしています。
Qiita内にそれ系の記事も書いてます。
エンジニアで稼ぐために大切な13のコト
WEBサービスで起業したい人に読んで欲しい18のコト

目次

1.1 スレッドの使い方
1.2 複数のスレッド起動時の注意点
1.3 スレッドの状態とサイクル
1.4 スレッドをつなぐ(join)
1.5 スレッドの同期化(Synchronized)

スレッド

JVMは1つの処理を実行していくので、
「バックグラウンドで処理をしたい」とかって平行処理をしたいならスレッドという仕組みを使う。
あたかもJVMが複数あって平行で処理しているように見せることができる。
分身の術的な。

スレッドの使い方

Threadクラスを継承して使うか、Runnableインターフェースを実装して使う

import java.util.*;
class SampleThread implements Runnable{ //スレッド定義。Runnnableインターフェースを実装する
  public void run(){  //スレッドを実行するとこのrun()内の処理がされる
    for(int i=0; i<10 ; i++){
     System.out.println(i);
    }
  }
}
public class Sample{
  public static void main(String[] args){
    System.out.println("入力してください");
    Thread t = new SampleThread(); //SampleThreadのインスタンス作成
    t.start(); //別スレッド開始
    new Scanner(System.in).nextLine(); //入力処理
  }
}

※run()は実行が終わると自動消滅するので、停止やcloseの指示はいらない

複数のスレッド起動時の注意点

JVMは複数のスレッドを高速に切り替えながら、平行に処理しているようにみせかけている。
切り替えはOSのスケジューリング機能を使うので、OSによってどのスレッドが順番に実行されていくかはわからない。(順番のコントロールはできない)

スレッドの状態とサイクル

スレッドは以下のような状態とサイクルで実行されている

初期状態 ⇒ 実行可能(プール)⇒ 実行中 ⇒ 終了
                      ⇒ 実行不可能(待機、スリープ、ブロック) ⇒ また実行可能へ
○初期状態 ・・・ newでオブジェクトが作成された状態。
○実行可能状態 ・・・ startメソッドを実行した時。実行可能な状態になっただけで、まだ実行はされない。
            スケジューラは実行可能状態のスレッドの中から独自の規則で実行していく。
○実行中 ・・・ 実行されてる
○実行不可能状態 ・・・ waitやsleepメソッドを実行した場合や、その他の事情で実行不可能へ。
             実行不可が解消されるとまた実行可能状態になる。
○終了 ・・・ runメソッドが完了した状態。一度終了したスレッドは二度とstarメソッドを実行できない。

スレッドをつなぐ

あっちのスレッドが終わらないとこっちのスレッドの処理は実行できない。という場合にjoinを使ってスレッド同士をつなげる。

class Sample implements Runnable{
 public void run(){
    for(int i=0; i<10; i++){
       System.out.println("スレッド実行中です");
    }
 }
}
public class Exec{
  public static void main(String[] args){
    Sample sp = new Sample();
    Thread t = new Thread(sp);
    t.start();
    try{
       t.join();
    }catch(InterruptedException e){ //joinはチェック例外のInterruptedExceptionを投げる
       e.printStackTrace();
    }
    System.out.println("mainスレッドが終わりました");
  }
}

スレッドの同期化

1つのオブジェクトを複数のスレッドで操作すると予想外の結果になったりするので、そういう時には同期化する。
(たとえば、同じ変数を複数のスレッドで1足して表示させようとすると「12345…」って順番にならない)

おかしくなる例
class Sample implements Runnnable{
  int i=0;
  pubic void run(){ adder(); }
  public void adder(){
    i++;
    System.out.println(Thread.currentThread().getName()+":"+n);
  }
}
public class Exec{
  public static void main(String[] args){
     Runnable r = new MyRunnable();
     Thread t1 = new Thread(r,"A");
     Thread t2 = new Thread(r,"B");
     Thread t3 = new Thread(r,"C");
     Thread t4 = new Thread(r,"D");
     t1.start(); t2.start(); t3.start(); t4.start();
  }
}

同期化するにはsynchronizedキーワードをつけることで、連続した一塊の処理として実行させる。

同期化した場合
class Sample implements Runnnable{
  int i=0;
  pubic void run(){ adder(); }
  synchronized public void adder(){
    i++;
    System.out.println(Thread.currentThread().getName()+":"+n);
  }
  synchronized public
}
public class Exec{
  public static void main(String[] args){
     Runnable r = new MyRunnable();
     Thread t1 = new Thread(r,"A");
     Thread t2 = new Thread(r,"B");
     Thread t3 = new Thread(r,"C");
     Thread t4 = new Thread(r,"D");
     t1.start(); t2.start(); t3.start(); t4.start();
  }
}

※syncronizedキーワードがついたメソッドは、ロック(カギ)を持っていて、そのロックを得てメソッドを実行しているスレッドがいる場合には、ほかのスレッドはそのスレッドを使えない。

24
29
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
29