JUC学习笔记-02-lock锁Condition的使用

Condition的认识

  • Condition中的await()方法相当于Object的wait()方法
  • Condition中的signal()方法相当于Object的notify()方法
  • Condition中的signalAll()相当于Object的notifyAll()方法。
  • Condition能够更加精细的控制多线程的休眠与唤醒。对于同一个锁,我们可以创建多个Condition,在不同的情况下使用不同的Condition,唤醒不同的线程,从而实现业务之间的通信。

ReentrantLock锁的使用

  • void lock(); // 无条件的锁;
  • void lockInterruptibly throws InterruptedException;//可中断的锁;
    使用ReentrantLock如果获取了锁立即返回,如果没有获取锁,当前线程处于休眠状态,直到获得锁或者当前线程可以被别的线程中断去做其他的事情;但是如果是synchronized的话,如果没有获取到锁,则会一直等待下去;
  • boolean tryLock();//如果获取了锁立即返回true,如果别的线程正持有,立即返回false,不会等待;
  • boolean tryLock(long timeout,TimeUnit unit);//如果获取了锁立即返回true,如果别的线程正持有锁,会等待参数给的时间,在等待的过程中,如果获取锁,则返回true,如果等待超时,返回false;
package condition;

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

/**
 * Description:
 * A 执行完 调用B
 * B 执行完 调用C
 * C 执行完 调用A
 * @author jiaoqianjin
 * Date: 2020/8/11 9:58
 **/

public class ConditionDemo {
    public static void main(String[] args) {
        Data3 data3 = new Data3();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                data3.printA();
            }
        },"A").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                data3.printB();
            }
        },"B").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                data3.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; // 1A 2B 3C

    public void printA() {
        lock.lock();
        try {
            /**
             *  业务代码 判断 -> 执行 -> 通知
             *  注意这里是用的是while循环判断,不能用if循环判断,如果使用if循环判断可能会出现虚假唤醒,
             *  当两个线程同时执行到这里的时候只判断一次就会导致同时持有锁,所以我们需要使用while循环
             */
            while (num != 1) {
                //这个await方法相当于Object的wait方法,表明该方法的调用者放弃锁的持有,进入等待池,只有使用condition1的signal方法才能唤醒进入准备池
                condition1.await();
            }
            System.out.println(Thread.currentThread().getName() + "==> AAAA" );
            num = 2;
            //这个signal方法相当于Object的notify方法, 唤醒使用condition2等待的线程进入准备池
            condition2.signal();
            TimeUnit.SECONDS.sleep(1);
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    public void printB() {
        lock.lock();
        try {
            // 业务代码 判断 -> 执行 -> 通知
            while (num != 2) {
                //这个await方法相当于Object的wait方法,表明该方法的调用者放弃锁的持有,进入等待池,只有使用condition2的signal方法才能唤醒进入准备池
                condition2.await();
            }
            System.out.println(Thread.currentThread().getName() + "==> BBBB" );
            num = 3;
            //这个signal方法相当于Object的notify方法, 唤醒使用condition3等待的线程进入准备池
            condition3.signal();
            TimeUnit.SECONDS.sleep(1);
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    public void printC() {
        lock.lock();
        try {
            // 业务代码 判断 -> 执行 -> 通知
            while (num != 3) {
                //这个await方法相当于Object的wait方法,表明该方法的调用者放弃锁的持有,进入等待池,只有使用condition3的signal方法才能唤醒进入准备池
                condition3.await();
            }
            System.out.println(Thread.currentThread().getName() + "==> CCCC" );
            num = 1;
            //这个signal方法相当于Object的notify方法, 唤醒使用condition1等待的线程进入准备池
            condition1.signal();
            TimeUnit.SECONDS.sleep(1);
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值