Java執行緒協作--生產者和消費者模式
阿新 • • 發佈:2019-01-29
生產者消費者模式是執行緒協作的經典應用,主要由具體產品類,容器類,生產者執行緒,消費者執行緒組成。具體表現形式為生產者執行緒生產產品往容器裡放置,當容器滿的時候,生產執行緒呼叫wait方法,使當前執行緒阻塞,而此時消費者執行緒在不斷的消費容器裡的產品,同時呼叫notifyf方法喚醒等待的生產者執行緒繼續生產;同理,當消費者將容器內產品消費完之後,消費者執行緒會進入阻塞狀態,而此時生產者執行緒在不斷繼續生產並喚醒消費者執行緒繼續消費。
注:如果當前有多個執行緒等待一個物件,notify方法只會喚醒一個,若需要喚醒多個執行緒,需要呼叫notifyAll方法
示例程式碼如下:
package com.trs.thread; import java.util.LinkedList; /** * Java多執行緒--生產者消費者模式 * @author xiayunan * @date 2018年7月18日 * */ public class TestConsumerProducer { private static DiningTable table = new DiningTable(); public static void main(String[] args) { System.out.println("========生產者消費者模式示例開始========"); Thread t1 = new Thread(new Producer(table)); Thread t2 = new Thread(new Consumer(table)); t1.start(); t2.start(); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("========生產者消費者模式示例結束========"); } /** * 肯德基全家桶 * @author xiayunan * @date 2018年7月18日 * */ static class KFCBucket{ private int id; public KFCBucket(int id) { this.id = id; } public int getId() { return id; } public void setId(int id) { this.id = id; } } /** * 容器類--取餐檯 * @author xiayunan * @date 2018年7月18日 * */ static class DiningTable{ private static int index = 0; private static int capacity = 100; private static LinkedList<KFCBucket> list = new LinkedList<KFCBucket>(); public synchronized void offer(KFCBucket k){ while(list.size()>=DiningTable.capacity){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.notify(); list.offer(k); System.out.println("生產了一個KFC全家桶,編號為"+k.getId()+" 產品總量為:"+DiningTable.list.size()); index++; } public synchronized KFCBucket poll(){ while(list.size()==0){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.notify(); KFCBucket bucket = list.poll(); System.out.println("消費了一個KFC全家桶,編號為"+bucket.getId()+" 產品總量為:"+DiningTable.list.size()); if(index>0){ index--; } return bucket; } } /** * 生產者類 * @author xiayunan * @date 2018年7月18日 * */ static class Producer implements Runnable{ private DiningTable table; public Producer(DiningTable table) { this.table = table; } @Override public void run() { for(int i=0;i<10;i++){ table.offer(new KFCBucket(i)); } } } /** * 消費者類 * @author xiayunan * @date 2018年7月18日 */ static class Consumer implements Runnable{ private DiningTable table; public Consumer(DiningTable table) { this.table = table; } @Override public void run() { for(int i=0;i<10;i++){ table.poll(); } } } }
執行結果: