자바 병발 중 Delay Queue 지연 대기 열 원리 분석

소개 하 다.
DelayQueue 대기 열 은 지연 대기 열 입 니 다.DelayQueue 에 저 장 된 요 소 는 Delayed 인터페이스의 요 소 를 실현 해 야 합 니 다.인 터 페 이 스 를 실현 한 후에 모든 요소 가 만 료 된 시간 이 있 는 것 과 같 습 니 다.대기 열 에서 take 요 소 를 가 져 올 때 요소 가 만 료 되 었 는 지 판단 하고 만 료 된 요소 만 팀 에서 작업 할 수 있 습 니 다.만 료 되 지 않 은 대기 열 은 남 은 만 료 시간 을 기 다 려 야 팀 을 나 갈 수 있 습 니 다.
소스 코드 분석
Delay Queue 대기 열 내 부 는 Priority Queue 우선 대기 열 을 사용 하여 데 이 터 를 저장 합 니 다.이 는 두 갈래 로 진행 되 는 우선 대기 열 을 사용 하고 ReentrantLock 자 물 쇠 를 사용 하여 스 레 드 동기 화 를 제어 합 니 다.내부 요 소 는 Priority Queue 를 사용 하여 데 이 터 를 저장 하기 때문에 Delayed 인 터 페 이 스 는 Comparable 인 터 페 이 스 를 실현 하여 우선 순 위 를 비교 제어 합 니 다.다음 코드 는 다음 과 같 습 니 다.

 public interface Delayed extends Comparable<Delayed> {
 
     /**
      * Returns the remaining delay associated with this object, in the
      * given time unit.
      *
      * @param unit the time unit
      * @return the remaining delay; zero or negative values indicate
      * that the delay has already elapsed
     */
    long getDelay(TimeUnit unit);
}
Delay Queue 의 구성원 변 수 는 다음 과 같 습 니 다.

 //  。
 private final transient ReentrantLock lock = new ReentrantLock();
 //     。
 private final PriorityQueue<E> q = new PriorityQueue<E>();
 
 /**
  * Leader-Follower   。
  * Thread designated to wait for the element at the head of
  * the queue.  This variant of the Leader-Follower pattern
 * (http://www.cs.wustl.edu/~schmidt/POSA/POSA2/) serves to
 * minimize unnecessary timed waiting.  When a thread becomes
 * the leader, it waits only for the next delay to elapse, but
 * other threads await indefinitely.  The leader thread must
 * signal some other thread before returning from take() or
 * poll(...), unless some other thread becomes leader in the
 * interim.  Whenever the head of the queue is replaced with
 * an element with an earlier expiration time, the leader
 * field is invalidated by being reset to null, and some
 * waiting thread, but not necessarily the current leader, is
 * signalled.  So waiting threads must be prepared to acquire
 * and lose leadership while waiting.
 */
private Thread leader = null;

/**
 * Condition signalled when a newer element becomes available
 * at the head of the queue or a new thread may need to
 * become leader.
 */
//   ,          Follower  ,          。
private final Condition available = lock.newCondition();

Leader-Follower 모드 의 변종 은 불필요 한 시간 대 기 를 최소 화 하 는 데 사 용 됩 니 다.하나의 스 레 드 가 Leader 로 선택 되 었 을 때 과거 실행 코드 논 리 를 지연 시 키 기 를 기다 리 고 다른 스 레 드 는 무기한 대기 해 야 합 니 다.take 나 poll 에서 돌아 오기 전에 대기 열의 머리 가 더 일찍 만 료 되 는 요소 로 바 뀔 때마다 leader 필드 는 빈 상태 로 초기 화 되 어 유효 하지 않 습 니 다.Leader 스 레 드 는 하나의 Follower 스 레 드 에 신 호 를 보 내야 합 니 다.깨 어 난 follwer 스 레 드 는 새로운 Leader 스 레 드 로 설정 되 어 있 습 니 다.
오퍼 조작

 public boolean offer(E e) {
     //     
     final ReentrantLock lock = this.lock;
     lock.lock();
     try {
         //       PriorityQueue     
         q.offer(e);
         //             ,         ,   Leader    ,          Leader 。
         if (q.peek() == e) {
            leader = null;
            available.signal();
        }
        //     
        return true;
    } finally {
        lock.unlock();
    }
}
offer 작업 전에 먼저 자 물 쇠 를 가 져 오 는 작업 을 합 니 다.즉,같은 시간 에 하나의 스 레 드 만 입장 할 수 있 습 니 다.
  • ReentrantLock 잠 금 대상 을 가 져 옵 니 다.
  • Priority Queue 우선 대기 열 에 요 소 를 추가 합 니 다
  • 만약 에 대기 열 에서 가장 먼저 만 료 된 요소 가 자신 이 라면 대기 열 이 원래 비어 있 었 다 는 것 을 설명 하기 때문에 Leader 를 리 셋 하여 Follower 스 레 드 가 Leader 스 레 드 가 될 수 있 음 을 알 립 니 다
  • 4.567917.마지막 으로 잠 금 해제 작업 을 합 니 다put 조작
    put 작업 은 사실 호출 된 offer 작업 으로 데 이 터 를 추가 하 는 것 입 니 다.다음은 소스 정보 입 니 다.
    
    public void put(E e) {
        offer(e);
    }
    
    take 조작
    
     public E take() throws InterruptedException {
         final ReentrantLock lock = this.lock;
         //        。
         lock.lockInterruptibly();
         try {
             //       。
             for (;;) {
                 //          ,       。
                 E first = q.peek();
                //            ,      ,            ,     。
                if (first == null)
                    //          ,     ,       。
                    available.await();
                else {
                    //                。
                    long delay = first.getDelay(NANOSECONDS);
                    //           0,       ,       。
                    if (delay <= )
                        //                  ,   。
                        return q.poll();
                    //           0,       。
                    //                  。
                    first = null; // don't retain ref while waiting
                    //         Leader  ,        。
                    if (leader != null)
                        //          。
                        available.await();
                    else {
                        //       。
                        Thread thisThread = Thread.currentThread();
                        //         Leader  。
                        leader = thisThread;
                        try {
                            //         。
                            available.awaitNanos(delay);
                        } finally {
                            //  Leader   null。
                            if (leader == thisThread)
                                leader = null;
                        }
                    }
                }
            }
        } finally {
            //        ,    Leader           Leader。
            if (leader == null && q.peek() != null)
                //       。
                available.signal();
            lock.unlock();
        }
    }
    
    4.567917.원 소 를 가 져 올 때 먼저 자물쇠 대상 을 가 져 옵 니 다
  • 최초 로 만 료 된 요 소 를 가 져 오지 만 대기 열 에서 요 소 를 꺼 내지 않 습 니 다
  • 최초 로 기한 이 지난 요소 가 비어 있 는 지,비어 있 으 면 현재 스 레 드 를 무기한 대기 상태 로 만 들 고 현재 잠 금 대상 을 양보 합 니 다
  • 만약 에 최초 로 기한 이 지난 요소 가 비어 있 지 않 으 면
  • 최초의 만 료 요소 의 남 은 만 료 시간 을 얻 고 만 료 되면 현재 요소 로 돌아 갑 니 다
  • 4.567917.기한 이 지나 지 않 았 다 면 남 은 시간 이 존재 한다 면 리더 대상 을 먼저 가 져 옵 니 다.만약 에 리더 가 이미 스 레 드 를 처리 하고 있다 면 현재 스 레 드 는 무기한 기다 리 고 리더 가 비어 있 으 면 먼저 리더 를 현재 스 레 드 로 설정 하고 현재 스 레 드 가 남 은 시간 을 기다 리 게 합 니 다마지막 으로 리더 스 레 드 를 빈 상태 로 설정 합 니 다4.567917.리더 가 비어 있 고 대기 열 에 내용 이 있 으 면 기다 리 는 대기 열 을 깨 웁 니 다poll 조작
    최초 로 만 료 된 요 소 를 가 져 옵 니 다.대기 열 헤더 에 만 료 된 요소 가 없 으 면 null 로 돌아 가 고,반대로 만 료 된 요 소 를 되 돌려 줍 니 다.
    
     public E poll() {
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             E first = q.peek();
             //                      ,   null。
             if (first == null || first.getDelay(NANOSECONDS) > 0)
                 return null;
             else
                //      。
                return q.poll();
        } finally {
            lock.unlock();
        }
    }
    
    작은 매듭
  • Delay Queue 는 무한 한 병발 지연 차단 대기 열 로 대기 열 에 있 는 요 소 는 반드시 Delayed 인 터 페 이 스 를 실현 해 야 한다.이에 따라 Comparable 인 터 페 이 스 를 비교 하 는 방법 이 필요 하 다
  • Leader-Follower 모드 의 변종 은 불필요 한 시간 대 기 를 최소 화 하 는 데 사 용 됩 니 다.하나의 스 레 드 가 Leader 로 선택 되 었 을 때 과거 실행 코드 논 리 를 지연 시 키 기 를 기다 리 고 다른 스 레 드 는 무기한 대기 해 야 합 니 다.take 나 poll 에서 돌아 오기 전에 대기 열의 머리 가 더 일찍 만 료 되 는 요소 로 바 뀔 때마다leader 필드 는 비어 있 는 것 으로 초기 화 되 며,leader 스 레 드 는 하나의 Follower 스 레 드 에 신 호 를 보 내야 합 니 다.깨 어 난 follower 스 레 드 는 새로운 Leader 스 레 드 로 설정 되 어 있 습 니 다
  • 자바 동시 다발 중 Delay Queue 지연 큐 원리 에 대한 분석 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.자바 Delay Queue 지연 큐 에 관 한 더 많은 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!

    좋은 웹페이지 즐겨찾기