Condition接口简介
本博客系列是学习并发编程过程中的记录总结。由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅。
接口简介#
Condition可以看做是Obejct类的wait()
、notify()
、notifyAll()
方法的替代品,与Lock配合使用。
当线程执行condition对象的await
方法时,当前线程会立即释放锁,并进入对象的等待区,等待其它线程唤醒或中断。
JUC在实现Conditon对象时,其实是通过实现AQS框架,来实现了一个Condition等待队列,这个在后面讲AQS框架时会详细介绍,目前只要了解Condition如何使用即可。
接口定义#
public interface Condition {
void await() throws InterruptedException;
long awaitNanos(long nanosTimeout) throws InterruptedException;
boolean await(long time, TimeUnit unit) throws InterruptedException;
boolean awaitUntil(Date deadline) throws InterruptedException;
void signal();
void signalAll();
}
使用示例#
wait-notify模式的一个典型应用就是可以实现生产者-消费者模式。让我印象很深是我毕业那年阿里巴巴校园招聘的一个笔试题:
有一个苹果箱,有10个人向这个箱子中每次随机放入一个苹果,有10个人每次随机从这个箱子中随机拿走一个苹果,同时需要满足箱子中的苹果总数不能超过50个。请用代码实现上面的场景(不能使用并发集合框架)
这个题目使用wait-notify模式可以很好地解决。下面使用Condition
模式来写下。
public class AppleBoxConditon {
private int appleCount;
private static Lock lock = new ReentrantLock();
private static Condition fullCondition = lock.newCondition();
private static Condition emptyCondition = lock.newCondition();
public void putApple() {
lock.lock();
try {
while (appleCount >= 10) {
try {
fullCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
appleCount++;
System.out.println("放入一个,当前盒子中苹果数:" + appleCount);
emptyCondition.signalAll();
} finally {
lock.unlock();
}
}
public void takeApple() {
lock.lock();
try{
while (appleCount <= 0) {
try {
emptyCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
appleCount--;
System.out.println("拿走一个,当前盒子中苹果数:" + appleCount);
fullCondition.signalAll();
}finally {
lock.unlock();
}
}
private static class AppleTaker implements Runnable {
private AppleBoxConditon appleBox;
public AppleTaker(AppleBoxConditon appleBox) {
this.appleBox = appleBox;
}
@Override
public void run() {
while (true) {
appleBox.takeApple();
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private static class ApplePutter implements Runnable {
private AppleBoxConditon appleBox;
public ApplePutter(AppleBoxConditon appleBox) {
this.appleBox = appleBox;
}
@Override
public void run() {
while (true) {
appleBox.putApple();
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
AppleBoxConditon appleBox = new AppleBoxConditon();
for (int i = 0; i < 20; i++) {
Thread t = new Thread(new AppleBoxConditon.ApplePutter(appleBox));
t.setName("ApplePutter:"+i);
t.start();
}
for (int i = 0; i < 20; i++) {
Thread t = new Thread(new AppleBoxConditon.AppleTaker(appleBox));
t.setName("AppleTaker:"+i);
t.start();
}
}
}
作者:程序员自由之路
出处:https://www.cnblogs.com/54chensongxia/p/12674541.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?