こんにちは、マルチスレッドを勉強し始めた者です。
私の見立てが間違っていなければ、表題のとおり、notifyAllがどのように他のスレッドにwaitの解除を通知しているかを知りたいです。
事の始まりはsleep sortをマルチスレッドで実装しようと思ったことです。
sleep sortは表示までの時間がずれないことが重要だと考えましたので、すべてのスレッドが一斉に動いたほうが良いと思いました。
そこでネットで調べたところ、waitとnotifyAllを使うことでこれが実現できると考えまして、この二つを用いて実装を試みました。
以下がコードになります。
環境:Windows 7 64bit
IDE:Eclipse 4.5.2
JDK:1.8
【SleepSortSample.java】
package exp01;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class SleepSortSample {
public synchronized void print(int n){
try {
wait();
Thread.sleep(n*10);
} catch (InterruptedException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
System.out.print(n+",");
}
public synchronized void note(){
notifyAll();
}
public static void main(String...args) {
SleepSortSample sleepSortSample = new SleepSortSample();
List<Integer> list = IntStream.range(0, 30).boxed().collect(Collectors.toList());
Collections.shuffle(list);
list.stream().forEach(c -> System.out.print(c + ","));
System.out.println();
for (Integer integer : list) {
new Thread(()->sleepSortSample.print(integer.intValue())).start();
}
new Thread(sleepSortSample::note).start();
}
}
------------------------------------------
しかしながら、このコードだと以下のように全くソートが行われていません。
【出力例】
17,19,18,24,13,0,27,14,6,29,28,20,5,25,12,16,26,23,3,22,10,9,21,1,11,8,2,15,4,7,
7,4,15,2,8,11,1,21,9,10,22,3,23,26,16,12,25,5,6,20,28,14,29,13,27,0,17,18,24,19,
このことから察するにnotifyAllはすべてのスレッドに同時に告知をするものではないことと、この告知に意外と時間がかかる、と言う風に推察しました。
ですが、公式ドキュメントを読んでもそのことについての記述が無いため、この考えが正しいかどうかの確認が出来ませんでした。
どなたかご存知の方がいれば教えていただきたく思います。
それともし可能ならすべてのスレッドを同期させる良い方法も教えていただけると幸いです。
よろしくお願いします。
※OKWAVEより補足:「Webシステム開発」についての質問です。
お礼
回答いただきましてありがとうございました! 理解しました! つまりこの処理は並列処理にはなっていない、ということですね? 結局今回の例で行けば30個スレッドがwaitしているところにnotifyAllがされると、ロックを取得できたものから順々にスレッドが実行されていく、という処理がなされると理解しました。 ということはnotifyAllは同時に実行してほしい時に使えるものではないと言うことですね。 ともあれ非常にわかりやすい回答でした! ありがとうございました。