[ThTest.java] class Runner implements Runnable{ public void run() { for(int i = 0; i < 3; i++) System.out.println("count :" + i); } }ま、こんな感じかな。 Runnerのrun()が実際に走るスレッドになります。 mainの方はまとめるとpublic class ThTest { public static void main(String[] args){ Runner runner = new Runner(); Thread t = new Thread(runner); t.start(); } }
public static void main(String[] args){
(new Thread(new Runner())).start();
}
という荒っぽいこともできます。
[MyQueue.java] import java.util.List; import java.util.ArrayList;synchronized(q)というのは、「このブロック内ではqに同時に複数アクセスできない」 ということを指定します。 ここで、複数の同じオブジェクトを対象とするsynchronizedでも、それぞれは連携して 動作し、同時に一つのブロックしか動きません。 例えばenqueue()とdequeue()が同時に呼ばれても、実際にqに触ることが出来るのは 片方だけで、もう片方はその直前でブロックされます。public class MyQueue{ private List q = new ArrayList();
public void enqueue(Object o){ synchronized(q){ q.add(o); q.notify(); } }
public Object dequeue() { synchronized(q){ while(q.isEmpty()) try{ q.wait();} catch (InterruptedExceprion e){} return q.remove(0); } } }
while(q.isEmpty()) q.wait(100);
という風に書くと、100m秒おきにキューが空でないかチェックし、空でなくなったら
次の処理に移ることができるようになっています。
また、ここで
while(q.isEmpty()) q.wait();
というふうに書くと、スレッドは永久にブロックされます。
って、本当に永久にブロックされたら困るわけで、このブロックを起こす手段がちゃんと用意されています。
それがq.notify()というメソッドで、どこか別のブロックでこのnotifyが呼ばれると、
waitは解除されます。ここでは、enqueueの方でnitify()してるので、
dequeueのwaitはキューが空でなくなったら解除されます。
一応、このキューのテストプログラム。
[Qtest.java]
import dla.MyQueue;
class Producer implements Runnable{
MyQueue q;
Producer(MyQueue _q){q = _q;}
public void run() {
for(int i = 0; i < 3; i++){
q.enqueue("Nexus" + i);
try{
Thread.sleep(1000);
} catch (Exception e){}
}
}
}
class Consumer implements Runnable{
MyQueue q;
public Consumer(MyQueue _q){q = _q;}
public void run() {
for(int i = 0; i < 3; i++){
try{
System.out.println((String)q.dequeue());
Thread.sleep(1);
} catch (Exception e){}
}
}
}
public class Qtest {
public static void main(String[] args){
MyQueue q = new MyQueue();
(new Thread(new Producer(q))).start();
(new Thread(new Consumer(q))).start();
}
}
データを入れるほうは1000msecおきにenqueueし、取り出すほうは1msecおきにdequeueするから、 waitが何度も呼ばれている計算になります。