Java의 차단 대기열 상세 설명

6217 단어 Java막힌 대기열
Java의 차단 대기열
1. 막힌 대기열은 무엇입니까?
차단 대기열(BlockingQueue)은 두 개의 추가 작업을 지원하는 대기열입니다.이 두 가지 추가 작업은 다음과 같습니다.
대기열이 비어 있을 때, 요소를 가져오는 라인은 대기열이 비어 있지 않기를 기다립니다.
대기열이 가득 차면 메모리 요소의 라인이 대기열이 사용할 수 있도록 기다립니다.
대기열을 막는 것은 생산자와 소비자의 장면에 자주 사용되고 생산자는 대기열에 원소를 추가하는 라인이며 소비자는 대기열에서 원소를 가져오는 라인이다.막힌 대열은 생산자가 원소를 보관하는 용기이고, 소비자도 용기에서 원소만 가져온다.
2. Java의 막힌 대기열
JDK에는 다음과 같은 7개의 차단 대기열이 있습니다.
  • ArrayBlockingQueue: 수조 구조로 구성된 경계 차단 대기열..
  • LinkedBlockingQueue: 체인 테이블 구조로 구성된 경계 차단 대기열..
  • PriorityBlockingQueue: 우선 순위 정렬을 지원하는 막힘 없는 대기열..
  • DelayQueue: 우선 순위 대기열을 사용하여 이루어지는 막힘 없는 대기열..
  • SynchronousQueue: 요소를 저장하지 않는 막힌 대기열..
  • LinkedTransferQueue: 체인 테이블 구조로 구성된 무계 차단 대기열..
  • LinkedBlockingDeque: 체인 테이블 구조로 구성된 양방향 차단 대기열.
  • ArrayBlockingQueue
    ArrayBlockingQueue는 수조로 이루어진 경계 차단 대기열입니다.이 대기열은 고급 프런트 아웃(FIFO) 원칙에 따라 요소를 정렬합니다.기본적으로 방문자의 공평한 방문 대기열을 보장하지 않는다. 이른바 공평한 방문 대기열은 막힌 모든 생산자 라인이나 소비자 라인을 가리킨다. 대기열이 사용할 수 있을 때 막힌 선후 순서에 따라 대기열에 접근할 수 있다. 즉, 먼저 막힌 생산자 라인은 먼저 대열에 원소를 삽입하고 먼저 막힌 소비자 라인을 먼저 대열에서 원소를 얻을 수 있다.통상적으로 공평성을 확보하기 위해 흡수량을 낮출 수 있다.우리는 다음 코드를 사용하여 공정한 차단 대기열을 만들 수 있다.
    ArrayBlockingQueue fairQueue = new ArrayBlockingQueue(1000,true);
    액세스의 공정성은 ReentrantLock 잠금을 통해 이루어집니다.
    LinkedBlockingQueue
    LinkedBlockingQueue는 체인 테이블로 이루어진 경계 차단 대기열입니다.이 대기열의 기본 및 최대 길이는 Integer입니다.MAX_VALUE.이 대기열은 선진적인 선출 원칙에 따라 원소를 정렬한다.
    PriorityBlockingQueue
    PriorityBlockingQueue는 우선 순위를 지원하는 무계 대기열입니다.기본적으로 요소는 자연 순서로 배열되며, 비교기comparator를 통해 요소의 정렬 규칙을 지정할 수 있습니다.요소는 오름차순으로 정렬됩니다.
    DelayQueue
    DelayQueue는 지연 시간 가져오기 요소를 지원하는 막힘 없는 대기열입니다.대기열은 PriorityQueue를 사용하여 수행됩니다.대기열의 요소는 Delayed 인터페이스를 구현해야 합니다. 요소를 만들 때 대기열에서 현재 요소를 가져올 수 있는 시간을 지정할 수 있습니다.지연 기간이 만료된 경우에만 대기열에서 요소를 추출할 수 있습니다.DelayQueue를 다음 응용 프로그램에 활용할 수 있습니다.
    캐시 시스템의 설계: DelayQueue로 캐시 요소의 유효기간을 저장할 수 있으며, 하나의 루트 순환으로 DelayQueue를 조회할 수 있으며, DelayQueue에서 요소를 얻을 수 있을 때 캐시 유효기간이 왔다는 것을 나타낸다.
    정시 임무 스케줄링.DelayQueue를 사용하여 당일 수행할 작업과 실행 시간을 저장하고 DelayQueue에서 작업을 가져오면 실행합니다. 예를 들어 TimerQueue는 DelayQueue를 사용하여 실행됩니다.
    Delayed 인터페이스 구현 방법
    우리는 ScheduledThreadPoolExecutor에서 ScheduledFutureTask 클래스를 참고할 수 있다.이 클래스는 Delayed 인터페이스를 실현했다.우선: 대상을 만들 때 time를 사용하여 이전 대상을 언제 사용할 수 있는지 기록합니다. 코드는 다음과 같습니다.
    
    ScheduledFutureTask(Runnable r, V result, long ns, long period) {
          super(r, result);
          this.time = ns;
          this.period = period;
          this.sequenceNumber = sequencer.getAndIncrement();
    }
    
    그리고 getDelay를 사용하면 현재 요소가 얼마나 오래 지연되는지 조회할 수 있습니다. 코드는 다음과 같습니다.
    
    public long getDelay(TimeUnit unit) {
     return unit.convert(time - now(), TimeUnit.NANOSECONDS);
        }
    
    구조 함수를 통해 알 수 있듯이 지연 시간 매개 변수 ns의 단위는 나초이다. 자신이 설계할 때 나초를 사용하는 것이 가장 좋다. 왜냐하면 getDelay는 임의의 단위를 지정할 수 있기 때문이다. 일단 나초를 단위로 하면 지연 시간이 나초보다 정확하지 않으면 번거롭다.사용할 때 현재 시간보다 시간이 적을 때 getDelay가 음수를 되돌려줍니다.
    마지막으로 우리는 타임을 사용하여 대기열의 순서를 지정할 수 있습니다. 예를 들어 가장 긴 시간을 대기열의 끝에 놓을 수 있습니다.
    
    public int compareTo(Delayed other) {
          if (other == this) 
            return 0;
          if (other instanceof ScheduledFutureTask) {
            ScheduledFutureTask x = (ScheduledFutureTask)other;
            long diff = time - x.time;
            if (diff < 0)
              return -1;
            else if (diff > 0)
              return 1;
        else if (sequenceNumber < x.sequenceNumber)
              return -1;
            else
              return 1;
          }
        long d = (getDelay(TimeUnit.NANOSECONDS)-other.getDelay(TimeUnit.NANOSECONDS));
          return (d == 0) ? 0 : ((d < 0) ? -1 : 1);
        }
    
    어떻게 시간 지연 차단 대열을 실현합니까
    시간 지연 차단 대기열의 실현은 매우 간단하다. 소비자가 대기열에서 원소를 얻을 때 원소가 시간 지연 시간에 도달하지 못하면 현재 라인을 막는다.
    
    long delay = first.getDelay(TimeUtil.NANOSECONDS);
    if(delay<=0){
     return q.poll ;// 
    }else if(leader!=null){
      //leader 
      available.await(); // 
    }else {
    // leader null, leader
    Thread thisThread = Thread.currentThread();
    try{
    leader = thisThread;
    // awaitNanos() delay 
    available.awaitNanos(delay);
    }finally{
     if(leader==thisThread){
       leader=null;
       }
     }
    }
    
    SynchronousQueue
    SynchronousQueue는 요소를 저장하지 않는 막힌 대기열입니다.모든put 작업은 take 작업을 기다려야 합니다. 그렇지 않으면 요소를 계속 추가할 수 없습니다.SynchronousQueue는 생산자의 스레드 처리 데이터를 소비자에게 직접 전달하는 패스맨으로 볼 수 있다.대기열 자체는 어떠한 요소도 저장하지 않고 전달적인 장면에 매우 적합하다. 예를 들어 한 라인에서 사용하는 데이터는 다른 라인에 전달하여 사용하는데 SynchronousQueue의 흡수량이 높다
    LinkedBlockingQueue와 ArrayBlockingQueue.
    그것은 공평한 접근 대기열을 지원한다.기본적으로 여전히 비공평한 전략 메커니즘이다
    LinkedTransferQueue
    LinkedTransferQueue는 체인 테이블 구조로 구성된 경계가 없는 TransferQueue 대기열입니다.다른 차단 대기열에 비해LinkedTransferQueue는tryTransfer와transfer 방법이 많습니다.
    transfer 방법
    만약에 현재 소비자가 원소를 수신하기를 기다리고 있다면(소비자가 테이크 () 방법이나 시간 제한을 가진poll () 방법을 사용할 때)transfer 방법은 생산자가 전송한 원소를 즉시 소비자에게 전송할 수 있다.만약 소비자가 원소를 수신하기를 기다리고 있지 않으면transfer 방법은 원소를 대기열의 tail 노드에 저장하고 이 원소가 소비자에게 소비될 때까지 기다린 후에 되돌려줍니다.
    tryTransfer 방법
    생산자가 전달한 원소가 소비자에게 직접 전달될 수 있는지를 탐색하는 데 쓰인다.만약 소비자가 원소를 수신하기를 기다리지 않으면false로 돌아갑니다.transfer 방법과 차이점은 tryTransfer 방법은 소비자가 수신하든 안 하든 방법이 즉시 되돌아온다는 것이다.트랜스퍼 방법은 소비자가 소비할 때까지 기다려야 돌아오는 것이다.
    시간제한이 있는tryTransfer(E,long timeout,Time Unit unit) 방법은 생산자가 전입한 원소를 소비자에게 직접 전달하려고 하지만 소비자가 이 원소를 소비하지 않으면 지정된 시간을 기다렸다가 되돌려주고, 시간 초과가 원소를 소비하지 않으면false를 되돌려주고, 시간 초과가 원소를 소비하면true를 되돌려준다.
    LinkedBlockingDeque
    LinkedBlockingDeque는 체인 테이블 구조로 구성된 양방향 차단 대기열입니다.이른바 양방향 대기열이란 대기열의 양쪽에서 요소를 삽입하고 옮길 수 있는 것을 가리킨다.양쪽 대열은 하나의 조작 대열의 입구가 많기 때문에 다중 노드가 동시에 대열에 들어갈 때 경쟁의 절반을 줄였다.다른 차단 대기열에 비해LinkedBlockingDeque는addFirst,addLast,offerFirst,offerLast,peekFirst,peekLast 등 방법이 많고, First 단어로 끝나는 방법으로 삽입, 가져오기 (peek) 또는 양쪽 대기열의 첫 번째 요소를 제거합니다.마지막 단어로 끝나는 방법은 양쪽 대기열의 마지막 요소를 삽입하거나 가져오거나 제거하는 것을 나타냅니다.또한 삽입 방법add는addLast와 같고, 제거 방법remove는removeFirst와 같습니다.그러나 테이크 방법은 테이크 퍼스트와 같다. Jdk의 버그인지 아닌지는 알 수 없지만 사용할 때는First와 Last 접두사가 있는 방법으로 더 잘 알 수 있다.LinkedBlockingDeque를 초기화할 때 대기열의 용량을 초기화하여 확장할 때 과도적으로 팽창하는 것을 방지할 수 있습니다.또한 양방향 차단 대기열은'작업 절도'모드에 활용할 수 있다.
    읽어주셔서 감사합니다. 여러분에게 도움이 되었으면 좋겠습니다. 본 사이트에 대한 지지에 감사드립니다!

    좋은 웹페이지 즐겨찾기