[java]またキューして実行 2009/02/25

Javaです。

またふただび、キューして実行。

以前も書いたけど、


どうも、wait,notify,が頭の中ですっきりしないので。
synchronizedされているところでしかwait,notifyできないです。
waitすると他のブロックされているスレッドが実行されます。

wait()はsynchronizedブロックの中で使用する。
wait()を呼び出すと、呼び出したスレッドはそこで実行を停止し、他のスレッドがsynchronizedの中に入って実行できる。
後から実行されたスレッドがnotify()を呼び出すと、そのスレッドがsynchronizedブロックから抜けた後にwait()を呼び出したスレッドが再実行される。Javaスレッドメモ(Hishidama's Java thread Memo)


上記の引用の通りですが、この「synchronizedブロックから抜けた後にwait()を呼び出したスレッドが再実行される」が理解できず、苦しみましたが、いまなら、なんとか頭でシュミレートできそうな気がします。

人に説明しろといわれたら、心もとないです。

またコード。
package th;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class TestEasyQue {

public static void main(String[] args) {

final Q q = new Q();
JFrame frame = new JFrame() {
{
JPanel panel = new JPanel() {
{
add(new JButton("start") {
{
addActionListener(new ActionListener() {
int i = 0;

@Override
public void actionPerformed(ActionEvent e) {
q.enqueue("addA " + i++);
q.enqueue(new Q.IExecutable() {
@Override
public void exec() {
try {
System.out
.println("*** >_<!! sleep!!");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}

}
});
}
});
}
});// end add
}
};

getContentPane().add(panel);
setSize(400, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
};

frame.setVisible(true);

}

static class Q {

LinkedList list = new LinkedList();
Thread worker = new Thread();

public Q() {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
synchronized (Q.this) {
while (!(0 < list.size())) {
try {
// System.out.println("i am wait...");
Q.this.wait();
} catch (Exception e) {
e.printStackTrace();
}
}//

}// synchronized

Object o = dequeue();

if (o instanceof IExecutable) {
exec((IExecutable) o);
continue;
}

System.out.println("*** " + o.toString());
}// while
}
}).start();
}

public synchronized void enqueue(Object o) {
list.addFirst(o);
notifyAll();
}

public synchronized Object dequeue() {
return list.removeLast();
}

void exec(IExecutable executable) {
try {
executable.exec();
} catch (Exception e) {
e.printStackTrace();
} catch (Throwable e) {
e.printStackTrace();
}
}

interface IExecutable {
public void exec();
}
}
}

: