06 003【JUC】多线程的生产者消费者及Condition介绍

生产者消费者

举例:现在两个线程,可以操作初始值为零的一个变量,实现一个线程对该变量+1,一个线程对该变量-1,实现交替,来10轮,变量初始值最终为零,下面每句都很干

package com.magic.juc0117;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Description
 * @Author Chelsea
 * @Date 2020/1/18 0:10
 */
class Aircondition{
    private int number =0;
    Lock lock = new ReentrantLock();
    //Lock support Condition
    //Lock replace synchronized  ,Condition replace monitor 官方文档
    //也就是当Lock取代synchronized时,Condition会替代monitor机制!!
    private Condition condition = lock.newCondition();

    public void increment() throws Exception{
        
        lock.lock();
        try{
            //1.判断
            while (number != 0){
                condition.await();
            }
            //2.干活
            number++;
            System.out.println(Thread.currentThread().getName()+"\t"+number);
            //3.通知
            condition.signalAll();
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }

    public void decrement () throws Exception{
        lock.lock();
        try{
            //1.判断
            while (number == 0){
                condition.await();
            }
            //2.干活
            number--;
            System.out.println(Thread.currentThread().getName()+"\t"+number);
            //3.通知
            condition.signalAll();
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
//    注释掉的是以synchronized举例 wait、notify 和 synchronized一起用
//    public synchronized void increment() throws Exception{
//        //1.判断
//        while (number != 0){
//            this.wait();
//        }
//        //2.干活
//        number++;
//        System.out.println(Thread.currentThread().getName()+"\t"+number);
//        //3.通知
//        this.notifyAll();
//    }
//
//    public synchronized void decrement () throws Exception{
//        //1.判断
//        while (number == 0){
//            this.wait();
//        }
//        number--;
//        System.out.println(Thread.currentThread().getName()+"\t"+number);
//        this.notifyAll();
//    }
}

/**
 * 重点!!
 * 1.高内聚低耦合前提下,线程操作资源类
 * 2.判断/干活/通知
 * 3.防止虚假唤醒  多线程的交互判断绝对不可以用if 要用while 官方文档Object.wait()方法
 * 重点   判断  wait  while循环加判断
 */
public class ProducerConsumerDemo04 {

    public static void main(String[] args) {
        Aircondition aircondition = new Aircondition();
        new Thread(() -> {
            for (int i = 0; i < 10 ; i++) {
                try {
                    aircondition.increment();
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        },"A").start();

        new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i < 10; i++) {
                    try {
                        aircondition.decrement();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }, "B").start();

        new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i < 10; i++) {
                    try {
                        aircondition.increment();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }, "C").start();

        new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i < 10; i++) {
                    try {
                        aircondition.decrement();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }, "D").start();
    }

    //判断如果用if 则2个线程一切正常,为什么4个线程用if会等于2? 用if不会再拉回判断可能同时唤醒两个+线程,就可能出现为2的情况,所以必须用while,if 仅仅是判断,while是循环加判断,用while可以防止虚假唤醒

}

Condition

lock可以实现精准控制,Condition大显身手:

package com.magic.juc0117;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class ShareData{ //低耦合高内聚封装
    private int number = 1;//A1 B2 C3
    private Lock lock = new ReentrantLock();
    //相当于一把锁配多把备用钥匙
    private Condition condition1 = lock.newCondition();
    private Condition condition2 = lock.newCondition();
    private Condition condition3 = lock.newCondition();

    public void print5(){
        lock.lock();
        try{
            //1.判断
            while (number !=1){
                //wait
                condition1.await();
            }
            //2.干活
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName()+"--"+i);
            }
            //3.通知
            number = 2;
            //如何通知线程2
            condition2.signal();
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void print10(){
        lock.lock();
        try{
            //1.判断
            while (number !=2){
                //wait
                condition2.await();
            }
            //2.干活
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName()+"--"+i);
            }
            //3.通知
            number = 3;
            //如何通知线程2
            condition3.signal();
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void print15(){
        lock.lock();
        try{
            //1.判断
            while (number !=3){
                //wait
                condition3.await();
            }
            //2.干活
            for (int i = 0; i < 15; i++) {
                System.out.println(Thread.currentThread().getName()+"--"+i);
            }
            //3.通知
            number = 1;
            //如何通知线程2
            condition1.signal();
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

}

/**
 * lock可以实现精准控制
 * 备注:多线程之间精准调用,实现A》B》C
 * 三个线程启动,要求如下
 *
 * AA打印5次,BB打印10次,CC打印15次
 * 接着
 * AA打印5次,BB打印10次,CC打印15次
 * 来10轮
 */
public class ConditionDemo {

    public static void main(String[] args) {
        ShareData shareData = new ShareData();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                shareData.print5();
            }
        },"AA").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                shareData.print10();
            }
        },"BB").start();

        new Thread(() -> {
            for (int i = 0; i < 15; i++) {
                shareData.print15();
            }
        },"CC").start();
    }
}

学习整理于JUC.

发布了53 篇原创文章 · 获赞 0 · 访问量 373

猜你喜欢

转载自blog.csdn.net/weixin_40778497/article/details/104039203