JUC个人学习笔记2---生产者消费者问题
根据b站UP主狂神说JUC课程所写的个人学习笔记 视频地址:https://www.bilibili.com/video/BV1B7411L7tE?from=search&seid=14761503393031794075
锁是什么?如何判断锁的是谁
4.生产者和消费者问题
synchronized版本 wait notify
public class A { 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 ++; System.out.println(Thread.currentThread().getName()+"=>"+num); //通知其他线程我加完毕了 this.notifyAll(); } //-1 public synchronized void decrement() throws InterruptedException { if (num ==0){ //等待 this.wait(); } num --; System.out.println(Thread.currentThread().getName()+"=>"+num); //通知其他线程我减完毕了 this.notifyAll(); } }
问题存在A B C D 4个线程
防止虚假唤醒问题把if改为while
public class A { 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.increment(); } 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 ++; System.out.println(Thread.currentThread().getName()+"=>"+num); //通知其他线程我加完毕了 this.notifyAll(); } //-1 public synchronized void decrement() throws InterruptedException { while (num ==0){ //等待 this.wait(); } num --; System.out.println(Thread.currentThread().getName()+"=>"+num); //通知其他线程我减完毕了 this.notifyAll(); } }
JUC版的生产者和消费者问题
通过lock可以找到condition
代码实现
public class B { public static void main(String[] args) { Data2 data = new Data2(); 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.increment(); } 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 Data2{ private int num = 0; Lock lock = new ReentrantLock(); Condition condition = lock.newCondition(); //+1 public void increment() throws InterruptedException { try { lock.lock(); //业务代码 while (num !=0){ //等待 condition.await(); //等待 } num ++; System.out.println(Thread.currentThread().getName()+"=>"+num); //通知其他线程我加完毕了 condition.signalAll();//唤醒全部 } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } //-1 public void decrement() throws InterruptedException { try { lock.lock(); while (num ==0){ //等待 condition.await(); } num --; System.out.println(Thread.currentThread().getName()+"=>"+num); //通知其他线程我减完毕了 condition.signalAll(); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } }
Condition实现精准通知唤醒
public class C { public static void main(String[] args) { Data3 data = new Data3(); new Thread(()->{ for (int i = 0; i < 10; i++) { data.printA(); } },"A").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { data.printB(); } },"B").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { data.printC(); } },"C").start(); } } class Data3{ private Lock lock = new ReentrantLock(); private Condition condition1 = lock.newCondition(); private Condition condition2 = lock.newCondition(); private Condition condition3 = lock.newCondition(); private int num = 1; public void printA(){ lock.lock(); try { while (num!=1){ condition1.await(); } System.out.println(Thread.currentThread().getName()+"AAA"); num = 2; condition2.signal(); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } public void printB(){ lock.lock(); try { while (num!=2){ condition2.await(); } System.out.println(Thread.currentThread().getName()+"BBB"); num =3; condition3.signal(); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } public void printC(){ lock.lock(); try { while (num!=3){ condition3.await(); } System.out.println(Thread.currentThread().getName()+"CCC"); num = 1; condition1.signal(); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } }