큐, 블로킹 큐

LinkedBlockingQueue 등 :

출처 :

큐 사이즈를 차단, 디폴트는 Integer.MAX_VALUE * / 개인 INT 최종 용량 인 / ** / ** * 큐 요소 / 개인 AtomicInteger 최종 카운트 = 새로운 AtomicInteger ()의 전류를 차단 번호;

* 블로킹 큐의 선두 과도 접합 노드 <E> 헤드 * 블록 큐 테일 노드 전용 과도 노드 <E> 마지막 / ** 획득 제거 잠금 등과 취 폴 같은 요소 * / 개인 최종 ReentrantLock와 takeLock = 새로운 ReentrantLock와 ();

 

특징 :

1 : 기본에 Integer.MAX_VALUE입니다 용량을 지정하지 않는 경우 : 바운드 형식의 큐입니다 (기본 값이 때 삭제 속도보다 속도 이상을 추가하면 메모리가 부족할 수 있습니다). 따라서 대기열을 피하기 위해 전체 부하 또는 표시에 너무 많은 메모리가 컴퓨터를 일으켰습니다.

2 : 각각의 데이터 큐 목록 추가에 LinkedBlockingQueue 노드가 상기 노드에 캡슐화 될 큐에 추가되는 헤드와 헤드 노드와 노드 테일 큐의 마지막 포인트.

3 : inkedBlockingQueue 실내는 추가입니다 takeLock 및 putLock 동시성 제어를 사용하고, 삭제 작업은 크게 처리량을 향상시킬 수 있도록하지 상호 배타적 인 작업을 동시에 수행 할 수 있습니다

 

 

인큐 방법

무효 넣어 (E 전자) 특징 :

1 : 큐가 가득, 블록 대기.

2 : 큐가 수행하고있는 경우 공간이 스레드가 추가 추가 된 일어나 계속 다음, 왼쪽 된 후 큐가 가득 차지 않은, 대기열에 노드 노드를 작성합니다. 큐가 요소 전에 넣어되지 않은 경우, 소비자 스레드 소비 후 각성 이루어집니다.

공공 무효 풋 (E 전자)가 예외 : InterruptedException {경우 (예 == NULL) 던져 새로운 NullPointerException이 () 발생, INT C = -1, 노드 <E> 노드 = 새 노드 <E> (E) 최종 ReentrantLock와 putLock =이. putLock; AtomicInteger 최종 카운트 = this.count // 인터럽트 획득 잠금 putLock.lockInterruptibly () {시도 큐가 가득 // 있는지, 만약 완전 차단 기다리는 동안 (count.get () == 용량) {notFull. AWAIT (); 큐 인큐 (노드)로} // 노드; C = count.getAndIncrement (); // 큐 (c + 1이면 스레드 웨이크 추가 조작이있는 경우, 사용 가능한 공간이 있는지 여부를 다시 판단 <용량) notFull.signal () {} 마지막 putLock.unlock ();} // 데이터 큐 소비 웨이크 스레드 소비가 있으면 경우 (c == 0) signalNotEmpty ()}

 

개인 무효 signalNotEmpty () {최종 ReentrantLock와 takeLock = this.takeLock; takeLock.lock (); {notEmpty.signal ()을 시도; 마지막} {takeLock.unlock (); }} 개인 무효 signalNotFull () {최종 ReentrantLock와 putLock = this.putLock; putLock.lock (); {notFull.signal ()을 시도; 마지막} {putLock.unlock (); }}

 

부울 제공 (E 전자) 특징 :

큐 요소를 사용할 수없는 경우, PUT 방식 기다리고 방해, 제안 직접적인 방법 방법 거짓 다릅니다.

공개 부울 쿠폰 (E E) {경우 (예 == NULL) 새로운 NullPointerException이 던져 (); 최종 AtomicInteger 카운트 = this.count, 경우 (count.get () == 용량) 반환 거짓; INT C = -1, 노드 <E> = 노드 새로운 노드 <E> (E) = 최종 ReentrantLock와 putLock this.putLock; putLock.lock () {시도 큐 공간을 사용할 // 노드로 노드에 요소가 있는지 여부를 판정한다 사용 가능한 공간은, // 그렇다면, 다음 또한 최대 스레드 웨이크를 추가합니다. 경우 (count.get () <용량) {인큐 (노드) C = count.getAndIncrement () 경우 (c + 1 <용량) notFull.signal () {}} 마지막 putLock.unlock ();} 만약 (c == 0) signalNotEmpty (); 창 C> = 0;}

 

 

부울 제공 (E 전자, 긴 시간 제한, TimeUnit와 단위) 特点 :

타임 아웃을 기다릴 awaitNanos의 조건을 사용하여, 타임 아웃 처리를 차단하는 방법을 제공하기 위해, 왜 여기에있는 동안 루프를 사용? awaitNanos 방법이 중단되고, 인터럽트 대기 스레드 중 방지하기 위해이기 때문에, 여기에 while 루프가 중단시 처리를 기다리는 사용, 나머지는 대기에 오래 기다릴 계속

 

디큐 방법

E take () 특징 :

1 : 큐가 비어 블록 대기.

2 : 큐는 취득에서 첫 번째 팀을 비우고 요소,이 큐의 요소가있는 일어나 계속하면 소비 후에서 소비자 스레드 요소의 삭제를 제거하지 않습니다. 당신이 사건을 넣으면 큐는 농산물 스레드 웨이크 추가 요소에 사용 후 제거 된 요소로 가득하다 전에.

공용 E 인출 ()는 예외 : InterruptedException을 발생 {E, X, INT C = -1, 최종 AtomicInteger 카운트 this.count =; 최종 ReentrantLock와 takeLock = this.takeLock; takeLock.lockInterruptibly을 (); 시도는 {// 큐는 대기를 차단하면서, 비어 (count.get () == 0) {notEmpty.await ()} X = 디큐 (); C = count.getAndDecrement (); // 큐 요소가 있다면 소비 스레드 소비까지 다음 웨이크 (c 존재 > 1) notEmpty.signal () {} 마지막 takeLock.unlock ();} // 제거 요소 큐가 가득 전에 생산 스레드 첨가 원소를 해제하는 경우 (c == 용량) signalNotFull (); 창 X; }

 

E 여론 조사 ()

공용 E 폴링 () {AtomicInteger 최종 카운트 this.count =; (count.get () == 0)는 null 경우; E는 X = NULL; INT C = -1; 최종 ReentrantLock와 takeLock = this.takeLock; takeLock.lock (); 시도 {경우 (count.get ()> 0) {X = 디큐 (); C = count.getAndDecrement (); 경우 (c> 1) notEmpty.signal (); }} {마지막 takeLock.unlock (); } 경우 (c == 용량) signalNotFull (); 반환 X; }

E 조사 (긴 시간 초과 예외 : InterruptedException 장치);

 

() 제거 : 삭제 요소 방법을

공공 부울 제거 (개체 O) {경우 (O == NULL) 반환 거짓; // 두 개의 잠금 모든 fullyLock ()를 고정, 시도는 {// 머리 요소에서 통과를위한 마지막 요소까지 (노드 <E> 트레일 = 헤드, p = trail.next ;! P = NULL; 흔적 = P, P = p.next) {경우이 요소를 제거하는 방법을 호출 동일한 요소를 발견 // 해제하는 경우 (o.equals (p.item)) {링크 해제 (P, 흔적) 반환 사실;}} 반환 거짓;} 마지막으로 {// 잠금 해제 개의 잠금 모든 fullyUnlock ();}}

 

-------------------------------------------------- -------------------------------------------------- -----------------------

 

ArrayBlockingQueue를 :

인큐 방법 :

1 : 추가 : 제안이 실제로 큐가 가득 찼을 때, ( "대기열 전체") 예외는 차단하지 않는 IllegalStateException을 발생, 방법 내부로 들어가.

 

2 : 제공 : 전체 큐는, true를 반환하고, 반환 거짓을 큐가 가득 찼을 때. 즉시 반환을 비는 차단.

// 큐, 진정한 전체 false를 반환 공공 부울 제공 (E 전자) {checkNotNull (예) 전체에서 ArrayBlockingQueue 등 번호의 서비스 반환; 요소가 빈 대기열 최종 ReentrantLock와 잠금 있는지 확인 // = this.lock; lock.lock (); // {잠금, 스레드 안전 시도를 얻을 경우 (카운트 == items.length) // 큐가 가득 찼을 때, 직접 반환 거짓 반환 거짓을 기다리고 차단하지, 그렇지 {삽입 (전자); // 큐 완전하지 않다, }} 마지막으로 {lock.unlock (); 바로 진정한 반환에}}

제공 (예, 시간 단위) : 데이터가 허위, 성공적으로 삽입 true를 반환 지정된 시간 반환 내에 큐에 삽입 할 수없는 경우, 대기 시간을 설정합니다.  

 

3 입력 : 대기열이없는 완전하지 직접 반환 값에있을 때, 대기 큐를 차단 대기열이 가득 차 있지 때까지 모든 다음 삽입 대기이다.

// ArrayBlockingQueue를 번호 넣어

공공 무효 넣어 (E e)이 예외 : InterruptedException를 {던졌습니다

  checkNotNull의 (e); // 또한 삽입 소자가 비어 있는지 확인

  최종 ReentrantLock와 잠금 this.lock =;

  lock.lockInterruptibly (); // 잠금 방법이 여기에 호출되지 않고, 통화가 lockInterruptibly 중단 될 수 있으며, 중단 반환 스레드가 될 수있는 잠금 반환에 중단 할 수 없습니다.

  {시도

    반면 (카운트 == items.length)

      notFull.await () 큐가 가득 차면 // 때문에 슬립 큐가 아닌 가득 찼음

    (E)를 삽입 //이 경우는이 소자에 삽입되고, 큐가 가득 차지 않은 나타낸다 방법의 여파에 비어 있지 않은 큐

  } 드디어 {

    () lock.unlock;

  }

}

 

디큐 방법 :

1 : 삭제 (), 큐가 비어 있지 않은 경우, 반환 제 팀 값 제거, 큐가 비어는 NoSuchElementException 쓰 ()는 예외

// AbstractQueue # 삭제,이 템플릿 방법, 정의 삭제 알고리즘 골격 큐 요소 및 큐의 요소에 특정 요소, 요소가 비어 반환, 예외가 발생, 특정 구현 여론 조사는 서브 클래스에 의해 구현되고,

공공 E 삭제 () {

  E = X 폴 (); // 큐에 의해 정의되는 인터페이스 메소드를 폴링

  경우 (X! = NULL)

    반환 X;

  그밖에

    () 새로운 예외 : NoSuchElementException를 던져;

}

 

2 : 첫번째 팀의 값을 제거 할 때 반환 큐가 비어 있지, 반환 큐를 널 (null)이 비어 : 설문 조사 (). 즉시 반환을 비는 차단.

// ArrayBlockingQueue를 # 여론 조사 = this.lock가 비어 () {최종 ReentrantLock와 잠금 널 공공 E 조사를 반환하지 않습니다, 큐 요소의 모든 요소를 ​​반환 lock.lock (); 시도 {반환 (== 0 계산)? 널 (null) : 추출물 ();} 마지막으로 {lock.unlock ();}}

 

// ArrayBlockingQueue를 # 추출물 전용 E 추출물 () {최종 개체 [] 항목 = this.items, E x는이 <E> 캐스트 (항목 [takeIndex]); // 큐 요소 항목 헤드 삭제 [takeIndex] = NULL // 큐 어레이의 첫 번째 요소 세트는 널 (null), GC가 용이하다 복구 takeIndex = INC (takeIndex) --count; notFull.signal (); // 대기 큐가 아닌 전체 스레드 알람 창 X이다}

설문 조사 (시간 단위) : 큐가없는 구멍 널 (null)이 지정된 시간 내에 반환 된 경우, 대기 시간을 설정, 팀은 다음 비우 첫 번째 값을 반환하지 않습니다 

 

3 : 인출 (E) 제 1 대기열이 비어 리턴 값 팀과 제거되지 않은 상기 큐가 빈 블록 대기 큐가 비어 있음 제 팀 값을 반환 할 때까지 대기하는 경우. 

방법 것으로, //이 방법은 잠금으로 호출되지 않습니다,하지만 전화가 lockInterruptibly 중단 될 수 lock.lockInterrupted (); // ArrayBlockQueue # ()이 예외 : InterruptedException가 {최종 ReentrantLock와 잠금 this.lock을 () = 던졌습니다 공공 E 걸릴을 스레드 인터럽트는 잠금 반환에 중단 될 수 없으며, 반환 할 수 있습니다. 시도 {(계산 == 0) // 큐 요소는 빈 notEmpty.await는 () 동안; // 큐가 비어 있지 않은 수면 반환 추출물 ()는 대기; //이 경우는 그 요소를 삭제, 큐가 비어 있지 대표, 이후에있는 동안 비 완전 큐} {마지막 lock.unlock ();}}

 

 

작은 확장 :

공개 INT 크기 () {최종 ReentrantLock와 잠금 this.lock =; () lock.lock; {반환 카운트를 시도; 마지막 {}) (lock.unlock; }}

상기 방법에 ArrayBlockingQueue 큐 크기가 카운트 변수는 ConcurrentLinkedQueue를 달리 큐 ConcurrentLinkedQueue를 크기마다 이송되며, 직접 반환되어, 높은 크기 방법 ConcurrentLinkedQueue를 효율보다 방법에 ArrayBlockingQueue 크기.

 

크기 () 메소드는 () 때문에 반복 크기 () 컬렉션을 통해, IsEmpty 함수보다 더 오래 걸립니다.

 

 

 

SynchronousQueue는

1 :이 각각 삽입 반대로 다른 제거 조작에 대응하는 스레드가 그 반대 기다리는 것이 아닌 대기 큐 버퍼이다 무제한이다. SynchronousQueue는 그러한 생산자 채널 가입 소비자,이 시나리오 "전달", "전환"또는 더 적합 : 스레드 동기화 정보 전달 / 시간 / 그것에 태스크 다른 스레드 기다려야하는 단계;

 

2 : 어떠한 내부에 SynchronousQueue 용량 들여다 헤더 요소 방법에 의해 취득 할 수없는 단독 요소를 삽입 할 수없고, 이는 단순히 "한 쌍의"대칭 조작 인 삽입 및 제거하는 것으로 이해 될 수있다. (예를 포함의 경우)의 특정 작업 컬렉션과의 호환성을 위해, SynchronousQueue는 빈 세트의 역할을했다.

스레드는 유휴 스레드가 다시 사용됩니다있을 경우 일반적인 시나리오는 그것의 사용에 스레드 풀, Executors.newCachedThreadPool ()에 SynchronousQueue는이다, 스레드 풀의 구조는 (새 작업이 올 때), 필요에 따라 새 스레드를 만들 그것은 60 초 동안 유휴 상태 재활용된다.

 

3 : 스레드의 생산자 또는 소비자의 대기 프로세스 SynchronousQueue는 선택적 공정성 정책 (기본 비 자본 모드). 공정 모드를 달성하기 위해 부정 모드 스택 (LIFO)는 큐 (FIFO)에 의해 달성된다. 데이터 구조는, FIFO는 일반적으로 더 높은 처리량을 지원하는 데 사용되는 이중 큐 (이중 큐) 및 듀얼 스택 (듀얼 스택)를 사용 LIFO 지지체 높은 스레드 로컬 저장소 (TLS).

다음과 같은 알고리즘을 차단 SynchronousQueue는 요약 될 수있다 :

1 : 큐 이중 (듀얼 큐) 및 데이터를 저장하기위한 듀얼 스택 (듀얼 스택)를 사용하면, 큐의 각 노드는 제조자 또는 소비자에게있을 수있다.

2 : 피 휴지통 유지율 및 기억 상실 자체 취소 노드 기준점

3 : 높은 경쟁 환경에서 스핀과 LockSupport 공원 / 언 파크, 달성 차단 처리량이 크게 향상된 스핀이 될 수 있습니다.

 

3 개 개의 내부 클래스가 있습니다 SynchronousQueue는

1 : 양도인 : 내부 추상 클래스 만 전송 방법. SynchronousQueue는 코드가 조합 될 수 있으므로 거의 모든 넣어 또는 통합 공정을 (이 전달 방법), 이중 큐 / 스택 데이터 구조 넣어 이후 및 동작은 대칭 수행된다.

출처 :

공공 무효 넣어 (E e)이 예외 : InterruptedException을 발생 {경우 (예 == NULL) (새 NullPointerException이 던져); 경우 (transferer.transfer (즉, 거짓, 0) == NULL) {Thread.interrupted (); () 새로운 예외 : InterruptedException 던져; }}

 

 

2 : TransferStack : 추상 클래스 상속 내부 양도인은 LIFO 데이터의 순서로, 비 공정 모드 큐 동작을위한 전송 방식을 달성했다. 방법 연결리스트 SNode하여 듀얼 스택 내부 얻을 수 있습니다.

헤드 노드가 일치하지 않은 // 모드)) {수행하기 위해 시도와 일치하려고하면 (h.isCancelled ()) // 이미 취소 // 머리 일치 된 수정 헤드 루프 casHead (시간, h.next) 계속; // 팝업 재시 // 다른 스택 경우에 새 노드 구축 (S, casHead (시간을 = snode (S, E, H, 이행 | 모드))) {(;;)에 대한 {// 루프와 일치 할 때까지 또는 웨이터 성공적인 검색 후에 // CAS의 노드가 s.next 사라지게 즉 m = m SNode s.next // m은 S의 일치 (m == NULL) {// 모든 웨이터가 사라 casHead (S하다면 널 (null)); // 새로운 노드 다음에 휴식을 사용; // 메인 루프를 다시 시작} SNode 백만 = m.next (m.tryMatch (들)) {// 일치하려고하면, 웨이크 업 // 노드의 = 널 (null)을 충족 팝 casHead m의 노드 (S, Mn)이 스레드; // 교체 헤드 모두 S와 m 리턴 (E) :;} (? (모드 == REQUEST) m.item s.item)를 팝업 성공적인 매칭 두 노드 팝 다른 // 손실 일치 s.casNext (m, MN); // 일치 도움말 링크 해제를 재순환, 노드 m를 삭제 실패}}} 다른 {첫 번째 노드 도움이 일치 // fulfiller SNode m = h.next; // m은 사라 현금이 웨이터 시간의 일치하는 경우 (m == NULL) //입니다 EAD (H, NULL); // 다른 성취 노드를 나타 {// 帮助 头 节点 匹配 SNode 백만 = m.next; 경우 (m.tryMatch (H)) // 도움이 일치 casHead (시간, MN); // 두 시간을 팝업 // 손실 일치 h.casNext (m, 백만) 다른 해요; // 도움말 링크 해제}}}}

 

설명 : 기본 알고리즘은 3 개주기 중 하나입니다 다음과 같은 동작을 시도하십시오

1 : 스택이 비어 있거나 이미이 시간에 두 가지 경우가 있으며, 동일한 모드가 포함되어있는 경우 : 비 계산 작업이 (제안, 설문 조사) 또는 만료 된 경우, 직접 반환 널하며 프레스 스택 대기로 다른 경우에는 현재 노드 넣어 노드가 깨끗한 방법에 통화 중 대기를 취소하면 (awaitFulfill 방법으로) 일치, 일치, 항목 일치하는 노드를 반환 취소 및 반환 널 위해 대기 노드를 취소 (나중에 별도로 설명).

2 : 스택 노드 (머리가) 스택 현재 노드에 넣어, (메소드 isFulfilling에 의해 결정)과 일치하고, 노드가 머리를 일치하도록 시도되지 않은 경우, 두 일치하는 노드가 성공적으로 스택에서 배출하고, 데이터 정합 노드를 반환한다. 다음과 같이 소스 코드를 isFulfilling :

m 비트 세트를 수행 한 경우 / ** true를 돌려줍니다. * / 정적 부울 isFulfilling INT (m) {창 (m 및 이행)! = 0; }

3 : 스택 노드 (헤드)의 상단이 이미 스택 노드는 일치하는 것을 나타내는 다른 데이터 노드를 보유하는 경우, 상기 매칭 동작이 노드 도와 다음 사이클의 첫 번째 단계에서 계속 시작합니다.

 

3 : TransferQueue : 추상 클래스 상속 내부 양도인은 FIFO 데이터의 순서대로 공정 대기열 동작 모드에 대한 전송 방식을 달성했다. 방법 링크리스트 큐함으로써 내부 이중 QNode 도모.

출처 : E 전송 (E 전자, 부울 타임, 긴 나노) {QNode의 = NULL; // 건설 / 필요 부울 isData = (! E = NULL)로 재사용; // 분석 넣어이나 걸릴 (;;) {QNode t = 꼬리, QNode의 시간 = 머리; 경우 (t == null이 || 시간 == NULL) // 톱 초기화되지 않은 값은 계속; // 스핀 경우 (시간 == t || t.isData == isData) {// 비우거나 같은 모드 QNode TN = t.next (! t = 꼬리) // 일관성 읽기를 계속하는 경우, 만약 (! TN = NULL) {// 이력 꼬리 노드, 꼬리 advanceTail을 지체 꼬리 노드를 업데이트 (t, TN) 계속하기} 경우 (타이밍 된 나노 && <= 0) //는 null 기다릴 수 // 현재 동작 신규 노드의 구성 및 테일로 (S == NULL) S = 새로운 QNode (전자의 경우, isData)) // 계속에서 링크에 실패한 경우 (! t.casNext는 (널 (null)는, S); // 사전 꼬리 advanceTail (t는, S); // 스윙 꼬리와 대기 // 대기 일치, 반환 일치하는 노드 아이템이 노드가 대기의 해제 경우 오브젝트 X = awaitFulfill (S, 즉, 타이밍, 나노) 창은, 경우 (X == S) {//는 대기는 (t가, S) 깨끗한 취소 // 대기가 해제되도록, 클리어의 노드는 null;} (의 경우!isOffList ()) {// S 노드는 아직) 이미 advanceHead (t 연결을 해제 아니다 대기열되지 // 연결 해제되는 경우 헤드 (X = NULL)을 // 및 자체 필드 s.item = S ;! // 항목을 잊었을 s.waiter = NULL;} 창 (X = NULL!) (E) X : 전자 // 취한다} else {// 상보 모드 QNode m = h.next (t = 경우 // 노드 이행하기! ! 꼬리 || m == null이 || H = 머리) 계속; // 일치하지 않는 읽기 개체 X = m.item; 경우 (! isData == (X = NULL) || // m 이미 성취 X == m | | //m.item=m, m은 m.casItem가 (X, e는)) {// 일치, CAS는 CAS advanceHead (시간, m) ;! // 추진 헤드 손실 지정된 요소 전자에 대한 항목을 수정 취소 계속 디큐 및 재 시도를 찾은 후 계속;} advanceHead (시간, m); // 성공적으로 일치, 머리가 성공적으로 성취 대기열 LockSupport.unpark (m.waiter); // m 웨이크 업 노드가 일치 스레드 리턴 (! X = NULL) ? (E) X : 전자;}}}?} 반환 (E) X (X = 널!) : 전자; // 테이크} 다른 {// 보완 모드 QNode m = h.next; // 노드가 == 경우 (t = 꼬리 || m를 충족하기! ! 널 (null) || H = 머리는) 계속; // 일치하지 않는 읽기 개체 X = m.item (! isData == (X = NULL)의 경우 || 이미 성취 // m X == m || //m.item ! = m, m은 m.casItem (X, E)를) 취소 {// 일치, CAS는 CAS advanceHead (시간, m) 손실 지정된 요소 전자에 대한 항목을 수정; // 사전 머리 뒤로 디큐 및 재 시도가 계속보고 계속 ;} advanceHead (시간, m); // 성공적으로 일치, 머리가 성공적으로 성취 대기열 LockSupport.unpark (m.waiter); // m 웨이크 업 노드가 일치 스레드 리턴 (X = 널!) (E) × : 전자;}}}?} 반환 (E) X (X = 널!) : 전자; // 테이크} 다른 {// 보완 모드 QNode m = h.next; // 노드가 == 경우 (t = 꼬리 || m를 충족하기! ! 널 (null) || H = 머리는) 계속; // 일치하지 않는 읽기 개체 X = m.item (! isData == (X = NULL)의 경우 || 이미 성취 // m X == m || //m.item ! = m, m은 m.casItem (X, E)를) 취소 {// 일치, CAS는 CAS advanceHead (시간, m) 손실 지정된 요소 전자에 대한 항목을 수정; // 사전 머리 뒤로 디큐 및 재 시도가 계속보고 계속 ;} advanceHead (시간, m); // 성공적으로 일치, 머리가 성공적으로 성취 대기열 LockSupport.unpark (m.waiter); // m 웨이크 업 노드가 일치 스레드 리턴 (X = 널!) (E) × : 전자;}}}E)) {// 일치, CAS는 CAS advanceHead (시간, m) 손실 지정된 요소 전자에 대한 항목을 수정; // 사전 머리 뒤로 디큐 및 재 시도를 계속보고 계속;} advanceHead (시간, m); // 일치 성공, 머리가 성공적으로 LockSupport.unpark (m.waiter) 성취 대기열 (! X = NULL) // m 웨이크 업 노드가 일치 스레드 수익 (E) × :? 전자;}}}E)) {// 일치, CAS는 CAS advanceHead (시간, m) 손실 지정된 요소 전자에 대한 항목을 수정; // 사전 머리 뒤로 디큐 및 재 시도를 계속보고 계속;} advanceHead (시간, m); // 일치 성공, 머리가 성공적으로 LockSupport.unpark (m.waiter) 성취 대기열 (! X = NULL) // m 웨이크 업 노드가 일치 스레드 수익 (E) × :? 전자;}}}

 

설명 : 기본 알고리즘은 다음과 같은 작업을 통해 두 사이클 중 하나입니다 :

1 : 큐가 비어 있거나 큐 (꼬리)과 같은 모드에서 꼬리 노드가 현재 노드가 큐의 끝을 넣어 추가하면, 통화 대기 awaitFulfill 노드가 일치합니다. 노드가 중단되거나 대기 대기 제한 시간 반환 null의 경우 리턴 매치는, 노드 항목을 일치합니다. 그 동안 우리는 꼬리 노드가 다른 스레드에 의해 수정되는 경우 다음, 꼬리 노드를 확인주기 뒤로 추진 꼬리를 계속 할 것입니다.

참고 : TransferStack.awaitFulfill 알고리즘과 일치 awaitFulfill 방법의 TransferQueue, 뒷면은 설명하지 더 이상됩니다.

2 : 꼬리 노드 (꼬리)의 작동 전류 모드가 다른 경우, 다음 일치시킬 수, 큐 헤드에서 헤드 노드는 노드가 지정된 요소의 E에 의해 보완 필드 CAS 항목을 수정하려고 보완 노드와 일치 후방보고 시작합니다, 경기 거꾸로 머리 전진과 일치하는 노드 웨이터 스레드, 그리고 마지막으로 반환 항목과 일치하는 노드를 깨어됩니다.

 

비교 스택 / 큐 노드 간극 (방법 청소)

1 : 노드가 취소되면 큐를 들어, 우리는 노드의 거의 항상 복잡한 시간-O1 정도 제거 할 수 있습니다. 그러나 꼬리에있는 노드는, 나중에 노드 취소 대기해야합니다.

2 스택을 위해, 우리는 전체 스택을 통과하는 O (N)의 시간 복잡도를 필요로하고 제거 할 노드 수를 결정하지만, 다른 스레드 병렬 스택 실행을 액세스 할 수있다.

 

 

 

 

 

 

 

-------------------------------------------------- -------------------------------------------------- -----------------------

요약 :

LinkedBlockingQueue 등 스레드 - 안전하고, 각 상태에 의해 구현 된 큐 중 기다리고 신호 대기와 알람 기능을 개체를 달성하기 위해 내부적으로 큐 두 ReentrantLock와 차단된다. 그것은 그 ArrayBlockingQueue를 다릅니다 :

  • 대기열 크기는 또한 레이트에서, 제거 속도보다 큰 경우에, 후자가 지정되어야하는 제한된 크기 ArrayBlockingQueue를 초기화되지만 LinkedBlockingQueue 등은 (는 Integer.MAX_VALUE) 무한한 수있다 바운스 될 수 있고, 다른 안 바운드의 경우는 메모리 오버 플로우 등의 문제가 발생할 수 있습니다.
  • 데이터 저장 컨테이너에 ArrayBlockingQueue 같은 배열을 사용하여 다른 데이터 저장 용기, 및 노드 오브젝트는 링크리스트 노드로서 이용 기반 LinkedBlockingQueue 등.
  • 저장 용기에 ArrayBlockingQueue 배열을 사용하기 때문에, 그렇게 추가 또는 모든 객체 인스턴스 소자가 삽입 또는 삭제 파괴되지 않지만 추가 노드에 LinkedBlockingQueue 객체 생성 것이다. 그것은 오랫동안 높은 걸릴 수 있습니다
  • 대량의 데이터의 동시 효과를 처리 할 때, GC에 대한 큰 영향이있을 수있다.
  • 로크 큐는 별도 LinkedBlockingQueue를 구현하면서 큐, ArrayBlockingQueue를 잠금 격리되지 않고, 로크 작동을 첨가하고, 동작 ReenterLock 채용 제거하는 구현 모두 추가 또는 삭제 로크 큐가 동일하지 달성 , putLock를 추가하는 데 사용되는 생성자와 높은 동시의 경우 병렬 데이터 큐에서 동작 할 수 있음이 크게 큐의 처리량을 늘릴 수 takeLock을 제거하는 방법을 사용 이 동시성은 큐의 전반적인 성능을 향상시킬 수 있습니다.

 

게시 50 개 원래 기사 · 원 찬양 2 · 조회수 2,342

추천

출처blog.csdn.net/eafun_888/article/details/93044980