JAVA-스레드 탱크 깊이 이해: shutdown, shutdown Now, awaitTermination
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;
}
이 두 가지 방법의 차이는 다음과 같다.
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
작업 대기열이 비어 있지 않으면 바로returnTIDYING
로 설정하고 설정이 성공하면 terminated
방법을 호출하여 하위 클래스에 종료를 알리고 종료가 끝난 후에ctl의 상태를TERMINATED
하고workerCount는 0으로 설정합니다.PS:
tryTerminate
함수에서 SHUTDOWN
상태인 경우 작업 대기열이 비어 있는지 판단해야 하며, 비어 있으면 계속 아래로 내려가고, 작업 대기열이 비어 있지 않으면 아직 작업이 수행되지 않은 상태로 되돌아오는 것을 의미한다.마지막 워커 실행이 끝난 후에 호출된 프로세스 워커 Exit 함수tryTerminate
도 호출되기 때문에 그때가 진정한 끝이다.tryTeminate 뒤에 있는 문장if(workerCountOf(c)!=0)
이 성립되면 작업 대기열이 비어 있지만 워커가 많다는 뜻이다. 그러면 최대 한 명의 IDLE 상태의 워커가 중단된다.이 단락은 구체적으로 무엇을 해야 할지 잘 모르겠다.이해가 안 돼.이로써 전체 스레드 탱크는 완전히 퇴출되었다.
작성자: NoneLing
링크:https://www.jianshu.com/p/b5e2283e869c
출처: 약서
약서의 저작권은 작가의 소유이며, 그 어떠한 형식의 전재도 작가에게 연락하여 권한을 수여받고 출처를 밝혀 주십시오.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Java 다중 스레드를 순차적으로 실행하는 몇 가지 방법 요약Java 다중 스레드를 순차적으로 실행하는 몇 가지 방법 요약 동료는 무심결에 이 문제를 제기하고 두 가지 방법을 직접 실천했다.물론 더 좋은 방법이 있을 거야. 방법 1 이런 방법은 비교적 흔히 볼 수 있는 해결 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.