問題は、2 つのスレッドがあり、1 つはリストへのライターであり、もう 1 つはリストからのリーダーです。ライターのループに大量の反復がある場合、リーダーがスタックすることがあります。その場合、そのリーダーはブロック (待機中ではない) になります。これは、通知を受信したことを意味しますが、ライターはモニターを解放しませんでしたか?
それで、なぜそうですか?これをどうするのが最善ですか?(睡眠は大丈夫ですか?)
import java.util.LinkedList;
import java.util.List;
public class Main {
private List<Object> m_calls = new LinkedList<Object>();
public void startAll(){
Thread reader = new Thread(new Runnable() {
@Override
public void run() {
while(true){
synchronized(m_calls){
while (m_calls.size() == 0) {
try {
System.out.println("wait");
m_calls.wait();
} catch (InterruptedException e) {
return;
}
}
m_calls.remove(0);
System.out.println("remove first");
}
}
}
});
Thread writer = new Thread(new Runnable() {
@Override
public void run() {
for(int i = 0; i < 15; i++){
// UN-comment to have more consistent behavior
/*try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
synchronized(m_calls){
m_calls.add(new Object());
m_calls.notifyAll();
System.out.println("sent");
}
}
}
});
reader.start();
writer.start();
}
public static void main(String[] args) {
new Main().startAll();
}
}
上記のコードを実行すると、異なる結果が得られます。
---------------------------------- 1回目の試み
送信待ち
送信
済み
送信
済み
送信
済み
送信
済み
送信
済み
送信
済み
送信
済み
送信
済み
送信
済み
送信
済み
送信
済み送信
済み送信
済み送信
済み送信済み
送信済み
送信済み
送信済み
送信
済み
---------------------------------- 2回目の試み
送信待ち
送信
済み
送信
済み
送信
済み
送信
済み
送信
済み
最初の
削除
最初の
削除
最初
の
削除
最初
の
削除
最初
の
削除
送信
済み
送信
済み
の
削除
最初
の
削除
------------------------------ コメントなしの sleep() - 期待通りの動作
送信待ち
削除
最初の
送信
待ち
削除最初の
送信
待ち
削除最初の
送信
待ち
削除最初の
送信
待ち
削除最初の
送信
待ち削除最初の
送信
待ち削除
最初の
送信
待ち削除最初の
送信
待ち削除
最初の
送信
待ち削除
最初の
送信
待ち削除最初の
送信
待ち
削除最初
の
送信
待ち
最初に
削除する
送信を
待つ最初に削除する
送信を
待つ
最初に削除
する
編集 1: リーダー スレッド (そのうちの 1 つ) はもう待機していないようで、むしろブロックされています。これは、モニターが通知を受信したように見えますが (notifyAll() の後)、ライター スレッドはループ内でロックを解放しません。 ...