终于搞懂Condition,await,signal
Condition接口通过ReentrantLock.newCondition获取ConditionObject实现类
方法说明
await:线程挂起LockSupport.park实现本地方法接口park
signal:线程退出等待,LockSupport.unpark。
在研究ScheduledThreadPoolExecutor的使用时了解核心方法take
ScheduledThreadPoolExecutor继承ThreadPoolExecutor,线程池自然需要阻塞队列中获取任务
ThreadPoolExecutor.runWorker---》getTask()---》workQueue.take():(workQueue.poll有超时时间情况)
take用到了leader-follower模式
take源码
public RunnableScheduledFuture<?> take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
for (;;) {
RunnableScheduledFuture<?> first = queue[0];
if (first == null)
available.await();
else {
long delay = first.getDelay(NANOSECONDS);
if (delay <= 0)
return finishPoll(first); // 已经到时间返回
first = null; // don't retain ref while waiting
if (leader != null) // 判断非当前线程在运行
available.await(); // 进入等待
else {
Thread thisThread = Thread.currentThread();
leader = thisThread; // 当前线程为要被执行线程
try {
available.awaitNanos(delay); // 倒计时等待 直到被唤醒或者超时
} finally {
if (leader == thisThread)
leader = null;
}
}
}
}
} finally {
if (leader == null && queue[0] != null)
available.signal();
lock.unlock();
}
}
使用的就是Condition线程间通信。
await的LockSupport.park(this);当前线程移除CPU片段,直到被唤醒或者中断。
available.awaitNanos等待过程中,如果延迟队列加入更优先处理的则为堆(小根堆)首,唤醒等待线程
public boolean offer(Runnable x) {
if (x == null)
throw new NullPointerException();
RunnableScheduledFuture<?> e = (RunnableScheduledFuture<?>)x;
final ReentrantLock lock = this.lock;
lock.lock();
try {
int i = size;
if (i >= queue.length)
grow();
size = i + 1;
if (i == 0) {
queue[0] = e;
setIndex(e, 0);
} else {
siftUp(i, e);
}
// 如果堆头是插入线程任务本身 则优先级最高,唤醒等待线程take循环再次进行,此时获取的RunnableScheduledFuture<?> first = queue[0]; first正式刚刚插入的最新任务线程。
if (queue[0] == e) {
leader = null;
available.signal(); // 唤醒等待线程(获取CPU片段)
}
} finally {
lock.unlock();
}
return true;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
2021-01-20 支付整理