感謝のプログラミング 10000時間

たどり着いた結果(さき)は、感謝でした。

【プログラミング 48.5時間目】Javaでマルチスレッドの基礎

スポンサーリンク

結城浩さんの信頼のわかりやすさ。
マルチスレッドの説明もとてもわかりやすかったです。

★★

・スレッドとは、「プログラムを実行している主体」のことである。

・1本のプログラムだけ実行されるのはシングルスレッドという。

・マルチスレッドとは、読んで字のごとく、複数のスレッドを並行して動かすこと。

・複数のスレッドを管理するのは、JVM

・複数のスレッドが互いに干渉しあう状況ではスレッドに1列に並んでもらうようにすること。それを排他制御という。

・マルチスレッドを使えば、非常に処理の重いメソッドを実行している裏で、別のスレッドが違う処理を進めることができる。

・synchronizedメソッドに入ると、そのインスタンスに対してロックをかける。他のメソッドは同じインスタンスのsynchronizedメソッドに入ることはできない。

・スレッドはメソッドに対して鍵をかけているのではなく、インスタンスに対して鍵をかけている。

・メソッドの全体ではなく。メソッドの一部分だけでロックをかけるときに使うのがsynchronizedブロック。

synchronized (ロックオブジェクト) {
	・・・
}

インスタンスメソッドの場合はそのインスタンス自身をロック。クラスメソッドの場合は、そのクラス自身をロックすることになる。

・スレッドはrunメソッドの実行が終了すれば動かない。
スレッドが自分で自分を終了したい場合には、runメソッドを終わらせればいい。

たとえばこんな感じ。
while(isRun)がtrueだったらスレッドが動き続けるけれど、外からisRunをfalseにしてやる。
すると、runメソッドが止まる(正確にいうと、runから「抜ける」)

package yuki;

public class ThreadTest extends Thread {
	
	private static boolean isRun = true;
	
	public static void main(String[] args) {
		ThreadTest test = new ThreadTest();
		test.start();
		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("Runを止めます");
		isRun = false;
	}
	
	public void run() {
		int i = 0;
		while (isRun) {
			i += 1;
			doEcho(i);
		}
	}
	
	public void doEcho(int i) {
		System.out.println("hoge" + i);
	}

}

結果

・・・
hoge998525
hoge998526
hoge998527
Runを止めます
hoge998528

10秒くらい動いて、止まった。

他のスレッドに仕事をさせておいて、そのスレッドの実行が終了したら、自分の仕事を再開したいときにつかうのは、

Threadのjoinメソッド

である。

void join() throws InterruptedException
タイムアウトなしで、スレッドの終了を待つ。

void join(long msec) throws InterruptedException
タイムアウトあり(msecミリ秒)でスレッドの終了を待つ

void join(long msec, int nsec) throws InterruptedException
タイムアウトあり(msecミリ秒 + nsecナノ秒)でスレッドの終了を待つ

joinでスレッドを待ち合わせるサンプル

package yuki;

public class ThreadJoinTest extends Thread {
	public static void main(String[] args) {
		ThreadJoinTest test = new ThreadJoinTest();
		System.out.println("Joinテストはじめます");
		
		//runを走らせる
		test.start();
		System.out.println("runが終わるまでmainスレッドは待ちます");
		try {
			//testの変数に入れたクラスのrunが走っている。このrunが終わるまで待つ
			test.join();
		} catch (InterruptedException ignore) {
			
		}
		System.out.println("Mainはちゃんと待ちましたよ。");
	}
	
	public void run() {
		for (int i = 0;true; i++) {
			try {
				Thread.sleep(10);
			} catch (InterruptedException ignore) {
				
			}
			if(i == 500) {
				System.out.println("i = " + i);
				break;
			}
		}
	}
}

結果はこうなる。

Joinテストはじめます
runが終わるまでmainスレッドは待ちます
i = 500
Mainはちゃんと待ちましたよ。