[JAVA学习笔记-88]DelayQueue实现Leader-Follower pattern

来源:互联网 发布:淘宝网品牌特卖会 编辑:程序博客网 时间:2024/06/09 18:34
DelayQueue实现Leader-Folloer pattern
1、当存在多个take线程时,同时只生效一个,即,leader线程
2、当leader存在时,其它的take线程均为follower,其等待是通过condition实现的
3、当leader不存在时,当前线程即成为leader,在delay之后,将leader角色释放还原
4、最后如果队列还有内容,且leader空缺,则调用一次condition的signal,唤醒挂起的take线程,其中之一将成为新的leader
5、最后在finally中释放锁


/**     * Retrieves and removes the head of this queue, waiting if necessary     * until an element with an expired delay is available on this queue.     *     * @return the head of this queue     * @throws InterruptedException {@inheritDoc}     */    public E take() throws InterruptedException {        final ReentrantLock lock = this.lock;        lock.lockInterruptibly();        try {            for (;;) {                E first = q.peek();                if (first == null)                    available.await();   /*队列为空则让当前线程在condition available上等待*/                else {                    long delay = first.getDelay(TimeUnit.NANOSECONDS);                    if (delay <= 0)      /*超时时间已到,直接从队列中取出元素,线程返回。*/                        return q.poll();                    else if (leader != null)   /*超时时间未到,且leader不为空(有线程正在处理),则当前调用线程在condition available上等待*/                        available.await();                    else {                        Thread thisThread = Thread.currentThread();                        leader = thisThread;    /*超时时间未到,且leader为空,则当前调用线程成为leader线程,leader是DelayQueue的private成员*/                        try {                            available.awaitNanos(delay);/*leader线程在condition available挂起直到超时时间满足,leader线程释放锁(atomically release the associated lock)*/                        } finally {/*使用try finally保证finally中的语句务必执行*/                            if (leader == thisThread)   /*问题:finally是在线程唤醒,重新竞争到锁,然后从 awaitNanos 继续执行,最后执行到finally*/                                leader = null;                        }                    }                }            }        } finally {            if (leader == null && q.peek() != null)   /*队列中有数据,且leader为空,则需要唤醒一下condition available等待队列上的线程,重新竞争锁,然后从挂起处继续执行*/                available.signal();            lock.unlock();    /*最后释放锁*/        }    }