WaitとNotifyで「生産者-消費者」モデルを実現


前に書く
実際の開発では、あるモジュールがデータを生成し、共有バッファを介してフローし、最後に別のモジュールが処理するシーンがよく見られます.データを生成するモジュールを、イメージ的に生産者と呼ぶ.データを処理するモジュールは、消費者と呼ばれ、中間の倉庫は任意のバッファタイプの記憶媒体に抽象化することができる.
では、このモデルにはどんなメリットがありますか?第一に、生産者と消費者を分離し、結合度を低下させることができるデカップリングである.第二に、生産者は製造したデータをバッファに捨てると、次のデータを生産することができ、基本的に消費者の処理速度に依存する必要はありません.3つ目は、生産者と消費者の速度の違いを調整することができ、両者の速度を一致させる必要はありません.
生産者-消費者モデル
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;

public class ProducerConsumer {

    public static void main(String[] args) throws InterruptedException {

        final int maxSize = 3;
        final LinkedList<String> queue = new LinkedList<String>();

        final Thread producer = new Thread("producer-thread") {
            @Override
            public void run() {
                while(true) {
                    synchronized (queue) {
                        while (queue.size() == maxSize) {
                            try {
                                System.out.println(Thread.currentThread().getName() + "         ,  consumer     ");
                                queue.wait();
                                System.out.println(Thread.currentThread().getName() + "   ,        ");
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        try {
                            TimeUnit.SECONDS.sleep(1);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        int index = queue.size();
                        queue.add("task-" + index);
                        System.out.println(Thread.currentThread().getName() + "     task-" + index);
                        queue.notifyAll();
                    }
                }
            }
        };

        Thread consumer = new Thread("consumer-thread") {
            @Override
            public void run() {
                while (true) {
                    synchronized (queue) {
                        while (queue.isEmpty()) {
                            System.out.println(Thread.currentThread().getName() + "         ,  producer     ");
                            try {
                                queue.wait();
                                System.out.println(Thread.currentThread().getName() + "   ,        ");
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        try {
                            TimeUnit.SECONDS.sleep(1);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + "    " + queue.poll());
                        queue.notifyAll();
                    }
                }
            }
        };

        producer.start();
        TimeUnit.MILLISECONDS.sleep(1); //   producer    
        consumer.start();

    }

}

出力結果
producer-thread     task-0
producer-thread     task-1
producer-thread     task-2
producer-thread         ,  consumer     
consumer-thread    task-0
consumer-thread    task-1
consumer-thread    task-2
consumer-thread         ,  producer     
producer-thread   ,        
producer-thread     task-0
producer-thread     task-1
producer-thread     task-2
producer-thread         ,  consumer     
consumer-thread   ,        
consumer-thread    task-0
consumer-thread    task-1
consumer-thread    task-2
consumer-thread         ,  producer     
producer-thread   ,        
producer-thread     task-0
producer-thread     task-1
producer-thread     task-2
producer-thread         ,  consumer     
consumer-thread   ,        
consumer-thread    task-0
consumer-thread    task-1
consumer-thread    task-2
consumer-thread         ,  producer     
producer-thread   ,        
producer-thread     task-0
producer-thread     task-1

Process finished with exit code 130 (interrupted by signal 2: SIGINT)

ライセンス契約
  • 本文は創作共有CC BY-NC-SA 3.0プロトコル
  • を遵守する.