자바 Count Downlatch 와 Cyclic Barrier 의 내부 실현 과 장면 상의 차 이 를 상세히 설명 합 니 다.
10572 단어 자바CountDownLatchCyclicBarrier
Countdown Latch 와 CyclicBarrier 는 자바 병행 프로 그래 밍 의 중요 한 도구 류 로 여러 스 레 드 병행 또는 병행 장면 에서 광범 위 하 게 응용 되 었 다.그러나 이들 은 내부 실현 과 사용 장면 에 있어 각각 중점 을 두 고 있다.
내부 구현 차이
전 자 는 전형 적 인 AQS 체제 와 CAS 체제 에 의존 하여 내부 상태의 교체 와 카운터 자체 의 변 화 를 컨트롤 하고 후 자 는 Lock 등 체제 에 다시 들 어가 내부 의 병행 안전성 과 일치 성 을 컨트롤 한다.
public class {
//Synchronization control For CountDownLatch.
//Uses AQS state to represent count.
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
Sync(int count) {
setState(count);
}
int getCount() {
return getState();
}
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
}
private final Sync sync;
... ...//
}
public class CyclicBarrier {
/**
* Each use of the barrier is represented as a generation instance.
* The generation changes whenever the barrier is tripped, or
* is reset. There can be many generations associated with threads
* using the barrier - due to the non-deterministic way the lock
* may be allocated to waiting threads - but only one of these
* can be active at a time (the one to which {@code count} applies)
* and all the rest are either broken or tripped.
* There need not be an active generation if there has been a break
* but no subsequent reset.
*/
private static class Generation {
boolean broken = false;
}
/** The lock for guarding barrier entry */
private final ReentrantLock lock = new ReentrantLock();
/** Condition to wait on until tripped */
private final Condition trip = lock.newCondition();
/** The number of parties */
private final int parties;
/* The command to run when tripped */
private final Runnable barrierCommand;
/** The current generation */
private Generation generation = new Generation();
/**
* Number of parties still waiting. Counts down from parties to 0
* on each generation. It is reset to parties on each new
* generation or when broken.
*/
private int count;
/**
* Updates state on barrier trip and wakes up everyone.
* Called only while holding lock.
*/
private void nextGeneration() {
// signal completion of last generation
trip.signalAll();
// set up next generation
count = parties;
generation = new Generation();
}
/**
* Sets current barrier generation as broken and wakes up everyone.
* Called only while holding lock.
*/
private void breakBarrier() {
generation.broken = true;
count = parties;
trip.signalAll();
}
/**
* Main barrier code, covering the various policies.
*/
private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
final ReentrantLock lock = this.lock;
lock.lock();
try {
final Generation g = generation;
if (g.broken)
throw new BrokenBarrierException();
if (Thread.interrupted()) {
breakBarrier();
throw new InterruptedException();
}
int index = --count;
if (index == 0) { // tripped
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null)
command.run();
ranAction = true;
nextGeneration();
return 0;
} finally {
if (!ranAction)
breakBarrier();
}
}
// loop until tripped, broken, interrupted, or timed out
for (;;) {
try {
if (!timed)
trip.await();
else if (nanos > 0L)
nanos = trip.awaitNanos(nanos);
} catch (InterruptedException ie) {
if (g == generation && ! g.broken) {
breakBarrier();
throw ie;
} else {
// We're about to finish waiting even if we had not
// been interrupted, so this interrupt is deemed to
// "belong" to subsequent execution.
Thread.currentThread().interrupt();
}
}
if (g.broken)
throw new BrokenBarrierException();
if (g != generation)
return index;
if (timed && nanos <= 0L) {
breakBarrier();
throw new TimeoutException();
}
}
} finally {
lock.unlock();
}
}
... ... //
}
실전.-각자 의 사용처 보 여주 기.
/**
* : 5 ,6 , ,
*/
public class UseCountDownLatch {
static CountDownLatch latch = new CountDownLatch(6);
/* */
private static class InitThread implements Runnable{
public void run() {
System.out.println("Thread_"+Thread.currentThread().getId()
+" ready init work......");
latch.countDown();
for(int i =0;i<2;i++) {
System.out.println("Thread_"+Thread.currentThread().getId()
+" ........continue do its work");
}
}
}
/* latch 0 */
private static class BusiThread implements Runnable{
public void run() {
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
for(int i =0;i<3;i++) {
System.out.println("BusiThread_"+Thread.currentThread().getId()
+" do business-----");
}
}
}
public static void main(String[] args) throws InterruptedException {
new Thread(new Runnable() {
public void run() {
SleepTools.ms(1);
System.out.println("Thread_"+Thread.currentThread().getId()
+" ready init work step 1st......");
latch.countDown();
System.out.println("begin step 2nd.......");
SleepTools.ms(1);
System.out.println("Thread_"+Thread.currentThread().getId()
+" ready init work step 2nd......");
latch.countDown();
}
}).start();
new Thread(new BusiThread()).start();
for(int i=0;i<=3;i++){
Thread thread = new Thread(new InitThread());
thread.start();
}
latch.await();
System.out.println("Main do ites work........");
}
}
/**
* : 4 , , ,
* ,
*/
class UseCyclicBarrier {
private static CyclicBarrier barrier
= new CyclicBarrier(4,new CollectThread());
//
private static ConcurrentHashMap<String,Long> resultMap
= new ConcurrentHashMap<String,Long>();
public static void main(String[] args) {
for(int i=0;i<4;i++){
Thread thread = new Thread(new SubThread());
thread.start();
}
}
/* */
private static class CollectThread implements Runnable{
@Override
public void run() {
StringBuilder result = new StringBuilder();
for(Map.Entry<String,Long> workResult:resultMap.entrySet()){
result.append("["+workResult.getValue()+"]");
}
System.out.println(" the result = "+ result);
System.out.println("do other business........");
}
}
/* */
private static class SubThread implements Runnable{
@Override
public void run() {
long id = Thread.currentThread().getId();
resultMap.put(Thread.currentThread().getId()+"",id);
try {
Thread.sleep(1000+id);
System.out.println("Thread_"+id+" ....do something ");
barrier.await();
Thread.sleep(1000+id);
System.out.println("Thread_"+id+" ....do its business ");
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
양자 총화1.Cyclicbarrier 결 과 를 모 은 Runable 스 레 드 는 반복 적 으로 실 행 될 수 있 습 니 다.await()방법 을 여러 번 터치 하면 countdownlatch 는 await()방법 을 여러 번 호출 할 수 있 습 니 다.cyclicbarrier 가 결 과 를 모 으 지 않 으 면 await()를 한 번 호출 하면 됩 니 다.
2.New cyclicbarrier(threadCount)의 스 레 드 수 는 실제 사용자 스 레 드 수 와 일치 해 야 합 니 다.
3.조정 스 레 드 동시 운행:countDownlatch 조정 작업 스 레 드 실행,외부 스 레 드 조정;cyclicbarrier 는 작업 스 레 드 간 에 서로 조 화 롭 게 운행 합 니 다.
4.구조 함수 에서 볼 수 있 듯 이 countDownlatch 가 실행 하 는 계수기 의 수량 은 스 레 드 수 와 관계 가 없습니다.cyclicbarrier 구조 에서 들 어 오 는 스 레 드 수 는 실제 실행 스 레 드 수 와 같 습 니 다.
5.countDownlatch 는 하위 스 레 드 의 실행 결 과 를 기반 으로 처리 할 수 없 으 며,cyclicbarrier 는 가능 합 니 다.
6.장면 을 사용 할 때 countdownlatch 는 프레임 워 크 로 딩 전의 일련의 초기 화 작업 등 장면 에 더욱 적합 합 니 다.cyclicbarrier 는 여러 사용자 스 레 드 가 실 행 된 후에 실행 결 과 를 종합 하여 계산 하 는 등 전형 적 인 장면 에 더욱 적합 합 니 다.
자바 Count Downlatch 와 Cyclic Barrier 의 내부 구현 과 장면 상의 차 이 를 상세히 설명 하 는 글 을 소개 합 니 다.자바 Count Downlatch 와 Cyclic Barrier 의 차이 점 에 대해 서 는 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 도 많은 응원 부 탁 드 리 겠 습 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.