生產者-消費者設計模式
/** * 生產者-消費者模式:是一個非常經典的多線程模式,在實際開發中應用非常廣泛的思想理念,在生產-消費模式中, * 通常有兩類線程,即N個生產線程和N個消費者線程。 * 生產者負責提交用戶請求,消費者線程則負責具體處理生產者提交的任務,在生產者和消費者之間通過共享內存緩存區進行通信。 * 典型的應用:MQ。 */ public class C05ProducerConsumer { public static void main(String[] args) throws InterruptedException { //任務 LinkedBlockingDeque<Task2> taskQueue = new LinkedBlockingDeque<Task2>(10);
//生產者 Producer producer1 = new Producer(taskQueue); Producer producer2 = new Producer(taskQueue); Producer producer3 = new Producer(taskQueue);
//消費者 Consumer consumer1 = new Consumer(taskQueue); Consumer consumer2 = new Consumer(taskQueue); Consumer consumer3 = new Consumer(taskQueue);
//線程池運行 ExecutorService pool = Executors.newCachedThreadPool(); pool.execute(producer1); pool.execute(producer2); pool.execute(producer3); pool.execute(consumer1); pool.execute(consumer2); pool.execute(consumer3);
Thread.sleep(13000); producer1.stop(); producer2.stop(); producer3.stop(); Thread.sleep(12000);
} } /** * 生產者 */ class Producer implements Runnable {
//任務 private BlockingQueue<Task2> taskQueue;
//用於停止運行,強制從主內存刷新 private volatile boolean isRun = true;
//id生成 private static AtomicInteger id = new AtomicInteger();
public Producer(BlockingQueue<Task2> taskQueue) { super(); this.taskQueue = taskQueue; }
/* * 不眠不休的生產任務 */ @Override public void run() { while (isRun) { Task2 task2 = new Task2(this.id.getAndIncrement(), Thread.currentThread().getName()); try { //模擬數據產生過程 Thread.sleep(2000); //2秒進不去隊列就失敗 boolean offer = this.taskQueue.offer(task2, 2, TimeUnit.SECONDS); System.out.println("生產 - " + task2.getId()); if (!offer) { System.out.println(id + " - 任務提交失敗"); } } catch (InterruptedException e) { e.printStackTrace(); } } }
/** * 停止運行 */ public void stop() { isRun = false; }
} /** * 消費者 */ class Consumer implements Runnable { //任務 private BlockingQueue<Task2> taskQueue;
public Consumer(BlockingQueue<Task2> taskQueue) { super(); this.taskQueue = taskQueue; }
/* * 消費者消費 */ @Override public void run() { while (true) { try { Task2 take = this.taskQueue.take(); //模擬數據消費過程 Thread.sleep(2000); System.out.println("消費:" + Thread.currentThread().getName() + " - " + take.getId()); } catch (Exception e) { e.printStackTrace(); } } } } class Task2 { private Integer id;
private String desc;
public Task2(Integer id, String desc) { super(); this.id = id; this.desc = desc; }
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getDesc() { return desc; }
public void setDesc(String desc) { this.desc = desc; } } |
/** * 案例一:生產者-消費者 * 採用JDK1.5的Lock的方式 */ public class J16MessagePCByLock { public static void main(String[] args) { ProductA productA = new ProductA(); ProducerA producer = new ProducerA(productA); ConsumerA consumer = new ConsumerA(productA); new Thread(producer,"p1").start(); new Thread(producer,"p2").start(); new Thread(consumer,"c1").start(); new Thread(consumer,"c2").start(); } } /** * 商品 */ class ProductA {
/** * 是否有商品 */ boolean isHashProduct = false;
/** * 自定義鎖 */ Lock lock = new ReentrantLock();
/** * 監視器 */ Condition condition = lock.newCondition();
/** * 生產 */ public void product() throws InterruptedException { //生產,上鎖 lock.lock();
while (isHashProduct) { //已有商品,進入等待,放棄CPU執行權、放棄鎖 condition.await(); }
isHashProduct = true; Thread.sleep(3000); System.out.println("生產一臺筆記本");
//喚醒消費者 condition.signalAll(); //生產完成,釋放鎖 lock.unlock(); } /** * 消費者 */ public void consumer() throws InterruptedException { //消費上鎖 lock.lock();
while (!isHashProduct) { //沒有商品,進入等待 condition.await(); }
isHashProduct = false; Thread.sleep(3000); System.out.println("消費一臺筆記本");
//喚醒生產者 condition.signalAll(); lock.unlock(); } } class ProducerA implements Runnable {
/** * 生產者 */ ProductA productA;
public ProducerA(ProductA productA) { super(); this.productA = productA; }
@Override public void run() { try { productA.product(); } catch (InterruptedException e) { e.printStackTrace(); } } } class ConsumerA implements Runnable {
/** * 生產者 */ ProductA productA;
public ConsumerA(ProductA productA) { super(); this.productA = productA; }
@Override public void run() { try { productA.consumer(); } catch (InterruptedException e) { e.printStackTrace(); } } } |
/** * 案例二:生產者-消費者 * 採用JDK1.5的Lock的方式:多個監視器 */ public class J17MessagePCByLockMC { public static void main(String[] args) { ProductB productB = new ProductB(); ProducerB producer = new ProducerB(productB); ConsumerB consumer = new ConsumerB(productB); new Thread(producer,"p1").start(); new Thread(producer,"p2").start(); new Thread(consumer,"c1").start(); new Thread(consumer,"c2").start(); } } /** * 商品 */ class ProductB {
/** * 是否有商品 */ boolean isHashProduct = false;
/** * 自定義鎖 */ Lock lock = new ReentrantLock();
/** * 監視器 */ Condition pCondition = lock.newCondition(); Condition cCondition = lock.newCondition();
/** * 生產 */ public void product() throws InterruptedException { //生產,上鎖 lock.lock();
while (isHashProduct) { //已有商品,進入等待,放棄CPU執行權、放棄鎖 pCondition.await(); }
isHashProduct = true; Thread.sleep(3000); System.out.println("生產一臺筆記本");
//喚醒消費者 cCondition.signal(); //生產完成,釋放鎖 lock.unlock(); } /** * 消費者 */ public void consumer() throws InterruptedException { //消費上鎖 lock.lock();
while (!isHashProduct) { //沒有商品,進入等待 cCondition.await(); }
isHashProduct = false; Thread.sleep(3000); System.out.println("消費一臺筆記本");
//喚醒生產者 pCondition.signal(); lock.unlock(); } } class ProducerB implements Runnable {
/** * 生產者 */ ProductB productB;
public ProducerB(ProductB productB) { super(); this.productB = productB; }
@Override public void run() { try { productB.product(); } catch (InterruptedException e) { e.printStackTrace(); } } } class ConsumerB implements Runnable {
/** * 生產者 */ ProductB productB;
public ConsumerB(ProductB productB) { super(); this.productB = productB; }
@Override public void run() { try { productB.consumer(); } catch (InterruptedException e) { e.printStackTrace(); } } } |