终于搞懂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;
}