자바 병발 라 이브 러 리 빨리 해결 해 드릴 게 요.

총람
컴퓨터 프로그램=데이터+알고리즘.
동시 프로 그래 밍 의 모든 근본 적 인 원인 은 데이터 의 정확성,스 레 드 의 효율 성 을 확보 하기 위해 서 이다.
자바 병렬 라 이브 러 리 는 모두 네 개의 큰 부분 으로 나 뉘 는데 다음 과 같다.

Executor 와 future 는 스 레 드 의 효율 성 을 확보 하기 위해 서 입 니 다.
Lock 과 데이터 구 조 는 데이터 의 일치 성 을 유지 하기 위 한 것 이다.
자바 가 프로 그래 밍 을 병행 할 때 사고 순 서 는...
자신의 데 이 터 를 잠 그 거나.제 공 된 데이터 구 조 를 사용 하여 데이터 의 안전성 을 확보 하거나
스 레 드 를 예약 할 때 Executor 를 사용 하여 더 좋 은 스 케 쥴 링 을 합 니 다.
2.Executor 총람

Executor 는 모든 작업 이 어떻게 실 행 될 지 에 대한 메커니즘(스 레 드 사용 세부 사항,스케줄 링 등 포함)과 분리 하 는 방법 을 제공 합 니 다.
관리자 에 해당 합 니 다.사장 이 관리자 에 게 임 무 를 수행 하 라 고 했 습 니 다.구체 적 으로 누가 집행 하고 언제 집행 하 든 상관 하지 않 습 니 다.
위의 그림 의 상속 관 계 를 보고 몇 가 지 를 소개 하 다.

내 장 된 스 레 드 탱크 는 기본적으로 모두 여기에 있다.newScheduledThreadPool 정시 에 실행 되 는 스 레 드 탱크newCachedThreadPool 캐 시 에 사 용 된 스 레 드newFixedThreadPool 고정 수량의 스 레 드 탱크newWorkStealingPool 큰 임 무 를 작은 임무 로 분해 하 는 스 레 드 탱크

3.계승 구조
구조 함수
정시 서비스 포함

public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
    return new DelegatedScheduledExecutorService
        (new ScheduledThreadPoolExecutor(1));
}
static class DelegatedScheduledExecutorService
        extends DelegatedExecutorService
        implements ScheduledExecutorService {
    private final ScheduledExecutorService e;
    DelegatedScheduledExecutorService(ScheduledExecutorService executor) {
        super(executor);
        e = executor;
    }
4.하나의 스 레 드 만 을 어떻게 보장 합 니까?
정시 에 실 행 될 때 이 방법 을 호출 합 니 다.호출 과정 은 다음 과 같 습 니 다.그 중의 주석 을 주의 하고 위 에서 아래로 호출 하 는 순서 입 니 다.

public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
                                                 long initialDelay,
                                                 long delay,
                                                 TimeUnit unit) {
    if (command == null || unit == null)
        throw new NullPointerException();
    if (delay <= 0)
        throw new IllegalArgumentException();
    ScheduledFutureTask<Void> sft =
        new ScheduledFutureTask<Void>(command,
                                      null,
                                      triggerTime(initialDelay, unit),
                                      unit.toNanos(-delay));
    RunnableScheduledFuture<Void> t = decorateTask(command, sft);
    sft.outerTask = t;
    //      
    delayedExecute(t);
    return t;
}
private void delayedExecute(RunnableScheduledFuture<?> task) {
    if (isShutdown())
        reject(task);
    else {
        //       
        super.getQueue().add(task);
        if (isShutdown() &&
            !canRunInCurrentRunState(task.isPeriodic()) &&
            remove(task))
            task.cancel(false);
        else
            //     
            ensurePrestart();
    }
}
//   worker    corePoolSize,      ,       
void ensurePrestart() {
    int wc = workerCountOf(ctl.get());
    if (wc < corePoolSize)
        addWorker(null, true);
    else if (wc == 0)
        addWorker(null, false);
}
5.어떻게 시간 을 정 해진 시간 에 집행 할 수 있 습 니까?

public ScheduledFuture<?> schedule(Runnable command,
                                   long delay,
                                   TimeUnit unit) {
    if (command == null || unit == null)
        throw new NullPointerException();
    RunnableScheduledFuture<?> t = decorateTask(command,
        new ScheduledFutureTask<Void>(command, null,
                                      triggerTime(delay, unit)));
    delayedExecute(t);
    return t;
}
매번 수행 할 때마다 다음 수행 시간 을 미 션 에 넣 습 니 다.

private long triggerTime(long delay, TimeUnit unit) {
    return triggerTime(unit.toNanos((delay < 0) ? 0 : delay));
}
/**
 * Returns the trigger time of a delayed action.
 */
long triggerTime(long delay) {
    return now() +
        ((delay < (Long.MAX_VALUE >> 1)) ? delay : overflowFree(delay));
}
Future Task 의 시간 은 LockSupport.parkNanos(this,nanos)를 통 해 정 해 집 니 다.LockSupport.park(this);

private int awaitDone(boolean timed, long nanos)
    throws InterruptedException {
    final long deadline = timed ? System.nanoTime() + nanos : 0L;
    WaitNode q = null;
    boolean queued = false;
    for (;;) {
        if (Thread.interrupted()) {
            removeWaiter(q);
            throw new InterruptedException();
        }
        int s = state;
        if (s > COMPLETING) {
            if (q != null)
                q.thread = null;
            return s;
        }
        else if (s == COMPLETING) // cannot time out yet
            Thread.yield();
        else if (q == null)
            q = new WaitNode();
        else if (!queued)
            queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
                                                 q.next = waiters, q);
        else if (timed) {
            nanos = deadline - System.nanoTime();
            if (nanos <= 0L) {
                removeWaiter(q);
                return state;
            }
            //    
            LockSupport.parkNanos(this, nanos);
        }
        else //    
            LockSupport.park(this);
    }
}
요약:Executor 는 작업 을 대기 열 에 두 고 생 성 된 future Task 입 니 다.그리고 생 성 된 작업 을 대기 열 에 정렬 하고 가장 가 까 운 시간 에 출발 해 야 할 작업 을 검사 합 니 다.만약 시간 이 되 지 않 는 다 면,다음 출발 시간 까지 라인 을 막 아 라.
메모:new Single Thread Scheduled Executor 는 하나의 스 레 드 만 있 습 니 다.아무리 많은 작업 을 제출 하 더 라 도 이 작업 들 은 순서대로 실 행 됩 니 다.이상 이 발생 하면 아래 작업 을 취소 하고 스 레 드 풀 도 닫 히 지 않 습 니 다.이상 포착 에 주의 하 십시오.
사용 하 다

ScheduledExecutorService single = Executors.newSingleThreadScheduledExecutor();
Runnable runnable1 = () -> {
    try {
        Thread.sleep(4000);
        System.out.println("11111111111111");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
};
Runnable runnable2 = () -> {
    try {
        Thread.sleep(4000);
        System.out.println("222");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
};
single.scheduleWithFixedDelay(runnable1,0,1, TimeUnit.SECONDS);
single.scheduleWithFixedDelay(runnable2,0,2, TimeUnit.SECONDS);
11111111111111 222 11111111111111 222 11111111111111
프로젝트 에서 스 레 드 풀 을 닫 는 것 에 주의해 야 합 니 다.

actionService = Executors.newSingleThreadScheduledExecutor();
        actionService.scheduleWithFixedDelay(() -> {
            try {
                Thread.currentThread().setName("robotActionService");
                Integer robotId = robotQueue.poll();
                if (robotId == null) {
                    //         
                    actionService.shutdown();
                } else {
                    int aiLv = robots.get(robotId);
                    if (actionQueueMap.containsKey(aiLv)) {
                        ActionQueue actionQueue = actionQueueMap.get(aiLv);
                        actionQueue.doAction(robotId);
                    }
                }
            } catch (Exception e) {
                //        
                LOG.error("",e);
            }
        }, 1, 1, TimeUnit.SECONDS);
총결산
이 글 은 여기까지 입 니 다.당신 에 게 도움 을 줄 수 있 기 를 바 랍 니 다.또한 당신 이 우리 의 더 많은 내용 에 관심 을 가 져 주 실 수 있 기 를 바 랍 니 다!

좋은 웹페이지 즐겨찾기