生产者和消费者问题
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 < 20; i++) {
- date.increment();
- }
- },"A").start();
- new Thread(()->{
- for (int i = 0; i < 20; i++) {
- date.decrement();
- }
- },"B").start();
- }
- }
- //判断等待、业务、通知
- class Date{
- private int number = 0;
- public synchronized void increment(){
- if (number!=0){
- try {
- //不等于0就让该线程等待
- this.wait();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- number++;
- // 打印加完后的值
- System.out.println(Thread.currentThread().getName()+"=>"+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 < 10; i++) dateC.plantA();
- },"A").start();
- new Thread(()->{
- for (int i = 0; i < 10; i++) dateC.plantB();
- },"B").start();
- new Thread(()->{
- 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();
- }
- }
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |