JAVA-스레드 탱크 깊이 이해: shutdown, shutdown Now, awaitTermination

7777 단어 다중 스레드
다음으로 이동:https://www.cnblogs.com/siriusckx/articles/3989057.html
https://www.jianshu.com/p/b5e2283e869c
1、shutdown()
물음: shutdown () 은 어떤 기능이 있습니까?
답: 새로 온 퀘스트 제출을 막으면 이미 제출한 퀘스트에 아무런 영향을 주지 않습니다.제출한 작업이 완료되면, 유휴 루트 (idleWorks) 를 중단합니다. 이 과정은 비동기적입니다.
질문: 새로 온 임무 제출을 어떻게 막습니까?
답: 스레드 탱크의 상태를 SHUTDOWN으로 변경하여 excute를 실행하여 임무를 제출할 때 상태가 RUNNING이 아닌 것으로 테스트되면rejectedExecution을 던져 새로운 임무의 제출을 막는 목적을 달성합니다.
Q: 제출된 작업에 영향을 미치지 않는 이유는 무엇입니까?
답: 작업을 중단하는 방법을 호출할 때workers의 작업을 검사합니다.worker에 대응하는 작업이 중단되지 않고 빈 라인이어야 중단됩니다.또한workQueue의 값은 일정한 논리적 순서에 따라works에 끊임없이 수송된다. 그러면 제출한 임무가 라인 자체의 논리적 집행에 따라 영향을 받지 않도록 보장할 수 있다.
 
2、shutdownNow()
질문: shutdownNow()는 어떤 기능이 있습니까?
답: 새로운 작업 제출을 막고 현재 실행 중인 루틴, 즉workers의 루틴을 중단합니다.또한workQueue의 작업을 제거하고 목록에 추가하여 되돌려줍니다.
질문: 새로 온 임무 제출을 어떻게 막습니까?
답: 스레드 탱크의 상태를 STOP로 변경하여 excute 제출 작업을 수행할 때 RUNNING이 아닌 상태가 테스트되면 RejectedExecution을 던져서 새로운 작업의 제출을 막는 목적을 달성합니다.
질문: 만약 내가 제출한 작업 코드 블록에서 어떤 자원을 기다리고 있는데 이 자원이 도착하지 않았는데 shutdownNow()를 실행하면 어떤 상황이 발생합니까?
답: shutdown Now () 방법을 실행할 때 활성화된 작업이 막히고 막힌 상태가 되면 shutdown Now () 는 막힌 작업을 한 번 중단합니다. 이 때 대응하는 루틴은InterruptedException입니다. 다음에 자원을 기다려야 한다면 정상적인 논리에 따라 자원이 도착하기를 기다립니다.예를 들어, 한 라인이sleep 상태에서 shutdownNow () 를 실행하면, 이 라인에interrupt () 요청을 하고,sleep () 방법은interrupt () 요청이 있을 때,InterruptedException () 을 던지고 계속 실행합니다.이 곳에서 주의해야 할 것은 활성화된 작업 중 여러 개의sleep () 가 있으면, 이 방법은 첫 번째sleep () 만 중단되고, 뒤의 것은 정상적인 실행 논리에 따라 진행됩니다.
 
3、awaitTermination(long timeout,TimeUnit unit)
간단하게 말하면 awaitTermination은 스레드 상태가 TERMINATED이거나 대기 시간이 지정된 시간에 도달할 때까지 기다린다.
 
4. 보충
//runState != RUNNINGSystem.out.println("-----isShutdown-------:"+tpe.isShutdown());//state == SHUTDOWN || state == STOPSystem.out.println("-----isTerminating----:"+tpe.isTerminating());//runState == TERMINATEDSystem.out.println("-----isTerminated-----:"+tpe.isTerminated());
ShutDown 함수에 대한 참고 사항:
/**
 * Initiates an orderly shutdown in which previously submitted
 * tasks are executed, but no new tasks will be accepted.
 * Invocation has no additional effect if already shut down.
 *
 * 

This method does not wait for previously submitted tasks to * complete execution. Use {@link #awaitTermination awaitTermination} * to do that. * * @throws SecurityException {@inheritDoc} */


질서정연한 닫기를 초기화하면 이전에 제출한 작업은 모두 실행되지만, 새로 제출한 작업은 작업 대기열에 넣을 수 없습니다.이전에 호출된 적이 있다면 다시 호출해도 소용없다.이 방법은 이전에 제출한 임무가 실행되기를 기다리지 않으며, 원한다면 awaitTermiante 방법을 사용해야 합니다.
함수의 코드는 다음과 같습니다.
public void shutdown() {
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        checkShutdownAccess();
        advanceRunState(SHUTDOWN);
        interruptIdleWorkers();
        onShutdown(); // hook for ScheduledThreadPoolExecutor
    } finally {
        mainLock.unlock();
    }
    tryTerminate();
}
  • 스레드 탱크의 자물쇠를 가져오고 checkShutdownAccess 방법으로 모든 스레드 탱크의 스레드가 ShutDown할 수 있는 권한이 있는지 확인합니다.
  • 호출advanceRunState 함수는 자전하는 CAS 조작을 통해ctl의 상태를 SHUTDOWN
  • 로 변경합니다
  • 호출interruptIdleWorkers 방법으로 모든 Idle 상태의 루트를 호출interrupt 방법으로 루트를 중단합니다.판단idle 상태는 워커의 ReentrantLock을 사용하여 호출tryLock을 시도하고 워커 라인이 자물쇠를 가져왔는지 확인한다. 워커의 자물쇠가 추가되면tryLock이 되돌아오는 것은false이다.
  • onShutDown() 방법을 통해 하위 클래스에 스레드 탱크가 ShutDown 상태에 있어야 한다고 알려줍니다.
  • 잠금 해제가 끝난 후 tryTermiante 방법으로 스레드 탱크를 종료하려고 시도합니다.

  • ShutDownNow 방법과 ShutDown 방법은 차이가 많지 않다.아래의 코드를 구체적으로 보아라
     public List shutdownNow() {
        List tasks;
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            checkShutdownAccess();
            advanceRunState(STOP);
            interruptWorkers();
            tasks = drainQueue();
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
        return tasks;
    }
    

    이 두 가지 방법의 차이는 다음과 같다.
  • shutDownNow 방법은 미완성 작업 대기열의 작업 목록을 되돌려줍니다
  • advanceRunState 방법에서 전송된 것은 STOP이지 SHUTDOWN이 아니다.

  • tryTermiante 메서드에서는 다음을 수행합니다.
     final void tryTerminate() {
        for (;;) {
            int c = ctl.get();
            if (isRunning(c) ||
                runStateAtLeast(c, TIDYING) ||
                (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
                return;
            if (workerCountOf(c) != 0) { // Eligible to terminate
                interruptIdleWorkers(ONLY_ONE);
                return;
            }
    
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
                    try {
                        terminated();
                    } finally {
                        ctl.set(ctlOf(TERMINATED, 0));
                        termination.signalAll();
                    }
                    return;
                }
            } finally {
                mainLock.unlock();
            }
            // else retry on failed CAS
        }
    }
    
  • 현재 스레드 풀의 운행 여부를 판단하거나 현재 스레드 풀의 상태비TIDYING( )가 크거나TIDYING 또는 TERMINATED 현재 스레드 상태SHUTDOWN 작업 대기열이 비어 있지 않으면 바로return
  • 현재 Worker Count가 0이 아니라면interruptedIdle Workers(true)를 호출하고 되돌아갑니다
  • CAS 조작을 통해ctl을TIDYING로 설정하고 설정이 성공하면 terminated 방법을 호출하여 하위 클래스에 종료를 알리고 종료가 끝난 후에ctl의 상태를TERMINATED하고workerCount는 0으로 설정합니다.

  • PS: tryTerminate 함수에서 SHUTDOWN 상태인 경우 작업 대기열이 비어 있는지 판단해야 하며, 비어 있으면 계속 아래로 내려가고, 작업 대기열이 비어 있지 않으면 아직 작업이 수행되지 않은 상태로 되돌아오는 것을 의미한다.마지막 워커 실행이 끝난 후에 호출된 프로세스 워커 Exit 함수tryTerminate도 호출되기 때문에 그때가 진정한 끝이다.tryTeminate 뒤에 있는 문장if(workerCountOf(c)!=0)이 성립되면 작업 대기열이 비어 있지만 워커가 많다는 뜻이다. 그러면 최대 한 명의 IDLE 상태의 워커가 중단된다.이 단락은 구체적으로 무엇을 해야 할지 잘 모르겠다.이해가 안 돼.
    이로써 전체 스레드 탱크는 완전히 퇴출되었다.
    작성자: NoneLing
    링크:https://www.jianshu.com/p/b5e2283e869c
    출처: 약서
    약서의 저작권은 작가의 소유이며, 그 어떠한 형식의 전재도 작가에게 연락하여 권한을 수여받고 출처를 밝혀 주십시오.

    좋은 웹페이지 즐겨찾기