海上生明月,天涯共此时。愿大家在这个团圆的夜晚,收获满满的温馨和喜悦,团圆美满,中秋快乐!
使用示例
ConditionDemoAwait :开始之后加锁,阻塞并释放锁
package com.caozz.demo5.concurrent;import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;public class ConditionDemoAwait implements Runnable{private Lock lock;private Condition condition;public ConditionDemoAwait(Lock lock, Condition condition){this.condition = condition;this.lock = lock;}@Overridepublic void run() {System.out.println("begin---ConditoiopnDemoAwait--");lock.lock();try{condition.await();System.out.println("end---ConditoiopnDemoAwait--");} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}
}
- ConditionDemoSinal :开始之后唤醒,此时并不会释放锁,所以会先结束,才会释放锁
package com.caozz.demo5.concurrent;import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;public class ConditionDemoSinal implements Runnable{private Lock lock;private Condition condition;public ConditionDemoSinal(Lock lock, Condition condition){this.condition = condition;this.lock = lock;}@Overridepublic void run() {System.out.println("begin---ConditoiopnDemoSinal--");lock.lock();try{//让当前线程阻塞,相当于Object.notify()condition.signal();System.out.println("end---ConditoiopnDemoSinal--");} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}
}
测试:
package com.caozz.demo5.controller;import com.caozz.demo5.concurrent.ConditionDemoAwait;
import com.caozz.demo5.concurrent.ConditionDemoSinal;
import com.caozz.demo5.concurrent.Consumer;
import com.caozz.demo5.concurrent.Producer;import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class Test {public static void main(String[] args) throws InterruptedException {Lock lock = new ReentrantLock();Condition condition = lock.newCondition();ConditionDemoAwait await = new ConditionDemoAwait(lock, condition);ConditionDemoSinal sinal = new ConditionDemoSinal(lock, condition);new Thread(await).start();Thread.sleep(10);new Thread(sinal).start();}
}
结果:
线程启动:await启动,执行开始后加锁,并阻塞,此时signal开始,并执行唤醒,然后signal结束,释放锁,被唤醒得await结束
如果启动不加sleep,可能会sinal先启动,那么sinal开始,唤醒,结束,然后await执行,阻塞,然后就会一直阻塞,无法结束,因为没有被唤醒
begin---ConditoiopnDemoAwait--
begin---ConditoiopnDemoSinal--
end---ConditoiopnDemoSinal--
end---ConditoiopnDemoAwait--
设计猜想
- 作用:实现线程的阻塞与唤醒
- 前提条件: 必须先要获得锁
- await、signal、signalall
- await:让线程阻塞,并且释放锁
- signal:唤醒阻塞的线程
- 加锁的操作,必然会涉及到AQS的阻塞队列
- await释放锁时,AQS队列中不存在已经释放锁的线程,那么被释放的线程去到了哪里?
- 唤醒被阻塞的线程:被阻塞的线程在哪里?
经过上面的思考,应该可以想到,通过await方法释放的线程,必须要有一个地方来存储,同时,阻塞的线程,是通过AQS还是单独地方来存储呢?
Condition等价于wait/notify
Condition是JUC里面得实现,所以不能使用wait/notify ,锁的实现不同。