终于搞懂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;
        }
posted @ 2022-01-20 15:27  倔强的老铁  阅读(396)  评论(0编辑  收藏  举报