生产者与消费者,采用notify()唤醒
package com.dwz.concurrency.chapter9; /** * 生产者和消费者之间的通信问题
* 执行wait()之后锁被释放 */ public class ProduceConsumerVersion4 { private final Object LOCK = new Object(); private int i = 0; private volatile boolean isProduced = false; private void produce() { synchronized(LOCK) { if(isProduced) { try { LOCK.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } else { i++; System.out.println("p->" + i); LOCK.notify(); isProduced = true; } } } private void consumer() { synchronized(LOCK) { if(isProduced) { System.out.println("c->" + i); LOCK.notify(); isProduced = false; } else { try { LOCK.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } }
测试代码(一个生产者与一个消费者)
public static void main(String[] args) { ProduceConsumerVersion4 pc = new ProduceConsumerVersion4(); new Thread("P") { @Override public void run() { while(true) { pc.produce(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); new Thread("C") { @Override public void run() { while(true) { pc.consumer(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); }
测试结果是线程安全的,程序正常结束
测试代码(多个生产者与多个消费者)
public static void main(String[] args) { ProduceConsumerVersion2 pc = new ProduceConsumerVersion2(); Stream.of("P1", "P2").forEach(n -> new Thread(n) { @Override public void run() { while(true) { pc.produce(); } } }.start() ); Stream.of("C1", "C2").forEach(n -> new Thread(n) { @Override public void run() { while(true) { pc.consumer(); } } }.start() ); }
测试结果:程序不能正常结束,被阻塞
多个生产者和多个消费者之间通信采用 notify()
缺点:会存在所有线程都等待的问题(wait)
分析:notify不能识别wait的身份,有可能消费者唤醒的是消费者,导致线程都blocked
改进方法,使用notifyAll()代替notify()
package com.dwz.concurrency.chapter9; import java.util.stream.Stream; /** * 多个生产者和多个消费者之间通信(线程安全版) */ public class ProduceConsumerVersion3 { private final Object LOCK = new Object(); private int i = 0; private volatile boolean isProducted = false; private void produce() { synchronized(LOCK) { if(isProducted) { try { LOCK.wait(); return; } catch (InterruptedException e) { e.printStackTrace(); } } i++; System.out.println(Thread.currentThread().getName() + "for P->" + i); LOCK.notifyAll(); isProducted = true; } } private void consumer() { synchronized(LOCK) { if(!isProducted) { try { LOCK.wait(); return; } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + "for C->" + i); LOCK.notifyAll(); isProducted = false; } } }
测试结果,程序是线程安全的,正常执行