いまさらながら、キューして。 2007/04/12

いまいち、notify,waitの使い方があいまいなってしまいます。
すんなり、理解できる人がうらやましい今日この頃です。

自分のためのメモ。

waitはオブジェクトのwaitセットにその実行中のスレッドが入ります。
notifiallはwaitセットにはいっているスレッドにたいして、動いてよいと命令します。
synchronizedはロックを取得します。
で、とても重要なのが、
waitセットに入るときには、スレッドがロックを持っていなければいけないです。
そして、waitセットに入ると取得したロックをいったんリリースします。

この振る舞いが頭に入ってないと、なんだかよくわからないことになってしまうように思われます。


簡単なサンプルコード


import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;

public class TestMainForQ {

public TestMainForQ() {

}

public static void main(String[] args) {

new TestMainForQ().go();

}

public void go() {
MyQueue myQueue = new MyQueue();
Producer producer = new Producer(myQueue);
Consumer consumer = new Consumer(myQueue);

Thread thread = new Thread(producer);
Thread thread2 = new Thread(consumer);
thread.start();
thread2.start();
}

class Producer implements Runnable {
MyQueue myQueue;

public Producer(MyQueue myQueue) {
this.myQueue = myQueue;
}

public void run() {
int cnt = 0;
while (true) {
System.out.println("*** producer add total:" + cnt++);
try {

System.out.println("test sleep...Zzzzz....");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

this.myQueue.enqueue(new Queue("aaaaa "));
System.out.println(myQueue.debug());
}

}

}

/**
* <p>
* キュー(Queue)
* </p>
*
* @author nakawaka
*
*/
class MyQueue {

LinkedList list = new LinkedList();

public MyQueue() {

}

/**
* <p>
* キューに追加します。
* </p>
*/
public synchronized void enqueue(Queue queue) {
list.addLast(queue);
notifyAll();
}

/**
* <p>
* キューからとりだします。
* </p>
*/
public synchronized Queue dequeue() {
if (list.size() == 0)
return (Queue) null;
Object object = list.removeFirst();
return (Queue) object;
}

/**
* <p>
* キューの総数。
* </p>
*
* @return
*/
public synchronized int count() {
return list.size();
}

public synchronized String debug() {
StringBuffer buffer = new StringBuffer();
Iterator iterator = list.iterator();
int i = 1;
while (iterator.hasNext()) {
Queue elem = (Queue) iterator.next();
buffer.append(++i + ":" + elem + "\n");
}
buffer.append("total:" + i + "\n");
return new String(buffer);
}

}

class Queue {
final Date date = new Date();
final String cmd;

public Queue(String cmd) {
this.cmd = cmd;
}

public String getCmd() {
return cmd;
}

public long unixTime() {
return date.getTime();
}

public String toString() {

return date + ":" + cmd;
}
}

class Consumer implements Runnable {
MyQueue myQueue;

public Consumer(MyQueue myQueue) {
this.myQueue = myQueue;
}

public void run() {
while (true) {
Queue queue = myQueue.dequeue();
if (queue != null) {
System.out.println(queue);
}

synchronized (this.myQueue) {
while (!(0 < myQueue.count())) {
try {
this.myQueue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

}
}

}


: