生产者和消费者问题
synchronized版-> wait/notify
juc版->Lock
面试:单例模式、排序算法、生产者和消费者、死锁
生产者和消费者问题 Synchronized版
package org.example.pc;public class A { public static void main(String[] args) { Date date = new Date(); new Thread(()->{ for (int i = 0; i { for (int i = 0; i "+number);// 通知其他线程,我完成了 this.notify(); } public synchronized void decrement(){ if (number!=1){ try { this.wait(); } catch (InterruptedException e) { throw new RuntimeException(e); } } number--; System.out.println(Thread.currentThread().getName()+"=>"+number); this.notify(); }}
存在的问题:A、B、C、D四个线程
在线程中判断业务完成唤醒等待应该使用while循环判断,而非if判断,因为if判断值判断一次,在线程中存在一种状态叫虚假唤醒。
JUC版生产者和消费者问题
代码实现
package org.example.pc;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;//判断等待、业务、通知public class Date { private int number = 0; private Lock lock = new ReentrantLock(); private Condition inCondition = lock.newCondition(); public void increment() { try { lock.lock(); while (number != 0) { inCondition.await(); } number++;// 打印加完后的值 System.out.println(Thread.currentThread().getName() + "=>" + number);// 通知其他线程,我完成了 inCondition.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void decrement() { try { lock.lock(); while (number != 1) { inCondition.await(); } number--; System.out.println(Thread.currentThread().getName() + "=>" + number); inCondition.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } }}
Condition 精准的通知唤醒线程
在传统并发编程中,通过notifily唤醒线程后所有线程都是随机获取到资源的,JUC中可以通过Condition来精准的控制要唤醒哪一个线程资源。任何一个新技术的出现都不会只是为了实现之前已有的效果
代码实现
package org.example.pc;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class C { public static void main(String[] args) { DateC dateC = new DateC(); new Thread(()->{ for (int i = 0; i { for (int i = 0; i { for (int i = 0; i < 10; i++) dateC.plantC(); },"C").start(); }}class DateC { private int number = 1; private Lock lock = new ReentrantLock(); private Condition inCondition1 = lock.newCondition(); private Condition inCondition2 = lock.newCondition(); private Condition inCondition3 = lock.newCondition(); public void plantA(){ try { lock.lock(); while (number!=1){ inCondition1.await(); } System.out.println(Thread.currentThread().getName()); number=2; inCondition2.signal(); }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); } } public void plantB(){ try { lock.lock(); while (number!=2){ inCondition2.await(); } System.out.println(Thread.currentThread().getName()); number=3; inCondition3.signal(); }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); } } public void plantC(){ try { lock.lock(); while (number!=3){ inCondition3.await(); } System.out.println(Thread.currentThread().getName()); number=1; inCondition1.signal(); }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); } }}