生产者和消费者问题
生产者和消费者问题
面试:单例模式,排序算法,生产者和消费者,死锁
Synchronized版
Synchronized 加锁 ; wait 等待; notify 唤醒;
/** * 线程之间的週信题:生产者和消赏者问题!等待唤,知唤 * 线程交替执行 A B操作问一个变量num=0 * A 生产num+1 * B 消费num-1 */public class Test01 { public static void main(String[] args) { Data data = new Data(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { data.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } },"A").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { data.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } },"B").start(); } }//等待,业务,通知class Data{ private int num = 0; //+1 public synchronized void increment() throws InterruptedException { if(num != 0){ //等待线程 this.wait(); } num++; //通知其他线程,+1完毕 System.out.println(Thread.currentThread().getName() + "->" + num); this.notifyAll(); } //-1 public synchronized void decrement() throws InterruptedException { if(num == 0){ //等待线程 this.wait(); } num--; //通知其他线程,-1完毕 System.out.println(Thread.currentThread().getName() + "->" + num); this.notifyAll(); } }
问题存在,现在是A,B线程,没有发现问题,如果有A,B,C,D四个线程,多一个加减线程,就会出现问题
问题原因:
线程会出现虚假唤醒的情况,线程等待应出现在while循环中,不是if判断中
public class Test01 { public static void main(String[] args) { Data data = new Data(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { data.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } },"A").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { data.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } },"B").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { data.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } },"C").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { data.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } },"D").start(); } }//等待,业务,通知class Data{ private int num = 0; //+1 public synchronized void increment() throws InterruptedException { while(num != 0){ //等待线程 this.wait(); } num++; //通知其他线程,+1完毕 System.out.println(Thread.currentThread().getName() + "->" + num); this.notifyAll(); } //-1 public synchronized void decrement() throws InterruptedException { while(num == 0){ //等待线程 this.wait(); } num--; //通知其他线程,-1完毕 System.out.println(Thread.currentThread().getName() + "->" + num); this.notifyAll(); } }
JUC版的生产者和消费者问题
通过Lock 找到 Condition
Lock lock = new ReentrantLock(); Condition condition = lock.newCondition();//加锁lock.lock();//释放锁lock.unlock();//等待线程condition.await();//通知其他线程condition.signalAll();
public class Test01 { /** * 线程之间的週信题:生产者和消赏者问题!等待唤,知唤 * 线程交替执行 A B操作问一个变量num=0 * A num+1 * B num-1 */ public static void main(String[] args) { Data data = new Data(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { data.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "A").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { data.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "B").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { data.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "C").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { data.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "D").start(); } }//等待,业务,通知class Data { private int num = 0; Lock lock = new ReentrantLock(); Condition condition = lock.newCondition(); //+1 public void increment() throws InterruptedException { lock.lock(); try { while (num != 0) { //等待线程 condition.await(); } num++; //通知其他线程,+1完毕 System.out.println(Thread.currentThread().getName() + "->" + num); condition.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } //-1 public void decrement() throws InterruptedException { lock.lock(); try { while (num == 0) { //等待线程 condition.await(); } num--; //通知其他线程,-1完毕 System.out.println(Thread.currentThread().getName() + "->" + num); condition.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } }//随机分布A->1B->0A->1B->0A->1B->0A->1B->0A->1B->0A->1B->0A->1B->0A->1B->0A->1B->0A->1B->0D->1C->0D->1
任何一个新的技术,绝对不是仅仅只是覆盖了原来的技术,优势和补充!
Condition 精准的通知和唤醒线程:可以有序执行线程
public class Test01 { /** * Condition 精准的通知和唤醒线程A B C */ public static void main(String[] args) { Data data = new Data(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { data.note1(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "A").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { data.note2(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "B").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { data.note3(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "C").start(); } }//等待,业务,通知class Data { private int num = 1; Lock lock = new ReentrantLock(); Condition condition1 = lock.newCondition(); Condition condition2 = lock.newCondition(); Condition condition3 = lock.newCondition(); public void note1() throws InterruptedException { lock.lock(); try { while (num != 1) { //等待线程 condition1.await(); } System.out.println(Thread.currentThread().getName() + "->" + num); num = 2; //唤醒指定的人 B condition2.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void note2() throws InterruptedException { lock.lock(); try { while (num != 2) { //等待线程 condition2.await(); } System.out.println(Thread.currentThread().getName() + "->" + num); //唤醒指定的人 C num = 3; condition3.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void note3() throws InterruptedException { lock.lock(); try { while (num != 3) { //等待线程 condition3.await(); } System.out.println(Thread.currentThread().getName() + "->" + num); //唤醒指定的人 A num = 1; condition1.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } }//线程顺序执行,比如生产线 : 下单 -》 支付 -》交易 -》物流A->1B->2C->3A->1B->2C->3A->1B->2C->3A->1B->2C->3
来源
生产者和消费者问题 - saxon宋 - 博客园
来源https://www.cnblogs.com/saxonsong/p/14727157.html