海上生明月,天涯共此时。愿大家在这个团圆的夜晚,收获满满的温馨和喜悦,团圆美满,中秋快乐!
使用示例
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;
}
@Override
public 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;
}
@Override
public 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 ,锁的实现不同。