찾다
Javajava지도 시간Java 스레드 풀을 정상적으로 종료하는 방법은 무엇입니까?

shutdown() 메서드

스레드 풀을 사용할 때 shutdown() 메서드를 호출한 후 스레드 풀은 더 이상 새로운 실행 작업을 허용하지 않습니다. 그러나 shutdown() 메서드를 호출하기 전에 작업 대기열에 배치된 작업은 여전히 ​​실행되어야 합니다. 이 메서드는 비차단 메서드이며 호출된 후 즉시 반환됩니다. 반환되기 전에 작업 대기열의 모든 작업이 실행될 때까지 기다리지 않습니다. 아래와 같이 shutdown() 메소드의 소스코드를 살펴보겠습니다.

public void shutdown() {
	//获取线程池的全局锁
	final ReentrantLock mainLock = this.mainLock;
	mainLock.lock();
	try {
		//检查是否有关闭线程池的权限
		checkShutdownAccess();
		//将当前线程池的状态设置为SHUTDOWN
		advanceRunState(SHUTDOWN);
		//中断Worker线程
		interruptIdleWorkers();
		//为ScheduledThreadPoolExecutor调用钩子函数
		onShutdown(); // hook for 
	} finally {
		//释放线程池的全局锁
		mainLock.unlock();
	}
	//尝试将状态变为TERMINATED
	tryTerminate();
}

일반적으로 shutdown() 메서드의 코드는 비교적 간단합니다. 먼저 스레드 풀을 닫을 수 있는 권한이 있는지 확인합니다. 권한이 있으면 작업 스레드를 중단할 수 있는 권한이 있는지 다시 확인합니다. 권한이 없으면 SecurityException 예외가 발생합니다. 코드는 다음과 같습니다.

//检查是否有关闭线程池的权限
checkShutdownAccess();
//将当前线程池的状态设置为SHUTDOWN
advanceRunState(SHUTDOWN);
//中断Worker线程
interruptIdleWorkers();

그 중 checkShutdownAccess() 메소드의 구현 코드는 다음과 같습니다.

private void checkShutdownAccess() {
	SecurityManager security = System.getSecurityManager();
	if (security != null) {
		security.checkPermission(shutdownPerm);
		final ReentrantLock mainLock = this.mainLock;
		mainLock.lock();
		try {
			for (Worker w : workers)
				security.checkAccess(w.thread);
		} finally {
			mainLock.unlock();
		}
	}
}

checkShutdownAccess() 메서드의 코드는 비교적 이해하기 쉽습니다. 스레드 풀의 전역 잠금이 사용되는 동안 스레드 풀을 닫을 수 있는 권한이 있는지 확인하는 것입니다.

다음으로 아래와 같이 advanceRunState(int) 메서드의 소스 코드를 살펴보겠습니다.

private void advanceRunState(int targetState) {
	for (;;) {
		int c = ctl.get();
		if (runStateAtLeast(c, targetState) ||
			ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
			break;
	}
}

advanceRunState(int) 메서드의 전체 논리는 현재 스레드 풀 상태가 지정된 상태인지 확인하는 것입니다. shutdown() 메서드에 전달된 상태는 SHUTDOWN이면 직접 반환됩니다. SHUTDOWN이 아닌 경우 현재 스레드 풀 상태를 SHUTDOWN으로 설정합니다.

다음으로 아래와 같이 showdown() 메서드에서 호출되는 InterruptIdleWorkers() 메서드를 살펴보겠습니다.

private void interruptIdleWorkers() {
	interruptIdleWorkers(false);
}

interruptIdleWorkers() 메서드가 InterruptIdleWorkers(boolean) 메서드를 호출하는 것을 볼 수 있습니다. 아래 그림과 같이 InterruptIdleWorkers(boolean) 메서드의 소스 코드를 계속 살펴보세요.

private void interruptIdleWorkers(boolean onlyOne) {
	final ReentrantLock mainLock = this.mainLock;
	mainLock.lock();
	try {
		for (Worker w : workers) {
			Thread t = w.thread;
			if (!t.isInterrupted() && w.tryLock()) {
				try {
					t.interrupt();
				} catch (SecurityException ignore) {
				} finally {
					w.unlock();
				}
			}
			if (onlyOne)
				break;
		}
	} finally {
		mainLock.unlock();
	}
}

위 코드의 전체 논리는 다음과 같습니다. 스레드 풀의 전역 잠금을 획득하고 모든 작업자 스레드를 순환하며 스레드가 중단되었는지 여부를 감지하고 그렇지 않은 경우 작업자 스레드가 잠금을 획득하고 스레드의 중단 메서드를 실행합니다. 스레드가 획득한 잠금입니다. 이때 onlyOne 파라미터가 true이면 루프를 종료합니다. 그렇지 않으면 모든 작업자 스레드를 반복하고 동일한 작업을 수행합니다. 마지막으로 스레드 풀의 전역 잠금이 해제됩니다.

다음으로 shutdownNow() 메서드를 살펴보겠습니다.

shutdownNow() 메서드

스레드 풀의 shutdownNow() 메서드가 호출되면 스레드 풀은 더 이상 새로운 실행 작업을 허용하지 않고 작업 큐에 존재하는 작업은 삭제되며 실행 중인 Worker 스레드는 또한 즉시 중단됩니다. 동시에 이 메서드는 현재 작업 대기열에서 삭제된 작업 목록인 반환 값을 갖습니다.

shutdownNow() 메소드의 소스코드는 다음과 같습니다.

public List<Runnable> shutdownNow() {
	List<Runnable> tasks;
	final ReentrantLock mainLock = this.mainLock;
	mainLock.lock();
	try {
		//检查是否有关闭权限
		checkShutdownAccess();
		//设置线程池的状态为STOP
		advanceRunState(STOP);
		//中断所有的Worker线程
		interruptWorkers();
		//将任务队列中的任务移动到tasks集合中
		tasks = drainQueue();
	} finally {
		mainLock.unlock();
	}
	/尝试将状态变为TERMINATED
	tryTerminate();
	//返回tasks集合
	return tasks;
}

shutdownNow() 메서드 소스 코드의 전체 논리는 shutdownNow() 메서드가 스레드 풀의 상태를 STOP으로 설정하고 모든 Worker 스레드를 중단하며, 작업 대기열의 모든 작업을 작업 컬렉션으로 이동하고 반환합니다.

shutdownNow() 메서드가 모든 스레드를 중단하면 InterruptWorkers() 메서드가 호출되는 것을 볼 수 있습니다. 다음으로, 아래와 같이 InterruptWorkers() 메서드의 소스 코드를 살펴보겠습니다.

private void interruptWorkers() {
	final ReentrantLock mainLock = this.mainLock;
	mainLock.lock();
	try {
		for (Worker w : workers)
			w.interruptIfStarted();
	} finally {
		mainLock.unlock();
	}
}

interruptWorkers() 메서드의 논리는 비교적 간단합니다. 즉, 스레드 풀의 전역 잠금을 획득하고, 모든 작업자 스레드를 순환하고, 스레드를 순차적으로 중단하고, 마지막으로 스레드 풀의 전역 잠금을 해제하는 것입니다.

interruptWorkers() 메서드 내부에서는 실제로 Worker 클래스의 InterruptIfStarted() 메서드가 호출되어 스레드를 중단합니다. 아래 그림과 같이 Worker 클래스의 InterruptIfStarted() 메서드 소스 코드를 살펴보겠습니다.

void interruptIfStarted() {
	Thread t;
	if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
		try {
			t.interrupt();
		} catch (SecurityException ignore) {
		}
	}
}

스레드를 중단하기 위해 Thread 클래스의 Interrupt() 메서드를 본질적으로 호출한다는 사실을 발견했습니다.

awaitTermination(long, TimeUnit) 메서드

스레드 풀이 waitTermination(long, TimeUnit) 메서드를 호출하면 호출자의 스레드를 차단하고 스레드 풀의 상태가 TERMINATED로 변경되거나 타임아웃될 때까지 반환하지 않습니다. 기간에 도달했습니다. 다음으로 아래와 같이 waitTermination(long, TimeUnit) 메소드의 소스코드를 살펴보겠습니다.

public boolean awaitTermination(long timeout, TimeUnit unit)
	throws InterruptedException {
	//获取距离超时时间剩余的时长
	long nanos = unit.toNanos(timeout);
	//获取Worker线程的的全局锁
	final ReentrantLock mainLock = this.mainLock;
	//加锁
	mainLock.lock();
	try {
		for (;;) {
			//当前线程池状态为TERMINATED状态,会返回true
			if (runStateAtLeast(ctl.get(), TERMINATED))
				return true;
			//达到超时时间,已超时,则返回false
			if (nanos <= 0)
				return false;
			//重置距离超时时间的剩余时长
			nanos = termination.awaitNanos(nanos);
		}
	} finally {
		//释放锁
		mainLock.unlock();
	}
}

위 코드의 전체 논리는 다음과 같습니다. 먼저 작업자 스레드의 배타적 잠금을 얻은 다음 루프를 통해 현재 스레드 풀이 이미 TERMINATED 상태인지 확인하고, 그렇지 않으면 true를 직접 반환합니다. 시간이 초과된 경우 false를 반환합니다. 타임아웃이 되지 않으면 타임아웃 전 남은 시간을 재설정하세요. 다음으로 다음 사이클에 진입하여 현재 Thread Pool이 TERMINATED 상태인지 다시 확인하고, 그렇다면 바로 true를 반환하고, 그렇지 않으면 타임아웃이 되었는지 확인하여 false를 반환한다. 타임아웃이 되지 않으면 타임아웃 전 남은 시간을 재설정하세요. 이 루프는 스레드 풀 상태가 TERMINATED가 되거나 시간 초과될 때까지 계속됩니다.

위 내용은 Java 스레드 풀을 정상적으로 종료하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명
이 기사는 亿速云에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제
@retryable 주석의 청취자가 지정된 경우에만 호출되는지 확인하는 방법은 무엇입니까?@retryable 주석의 청취자가 지정된 경우에만 호출되는지 확인하는 방법은 무엇입니까?Apr 19, 2025 pm 03:09 PM

Springretry에서 @retryable 주석에 대한 청취자를 올바르게 구성하는 방법은 무엇입니까? 봄 사용 ...

Spring WebFlux에서 ServerB에서 ServerC로 재해 복구 재 시도 메커니즘을 구현하는 방법은 무엇입니까?Spring WebFlux에서 ServerB에서 ServerC로 재해 복구 재 시도 메커니즘을 구현하는 방법은 무엇입니까?Apr 19, 2025 pm 03:06 PM

Springwebflux를 사용하여 LLMGateway의 재해 복구 재 시도 메커니즘을 구현합니다. llmgateway를 구축 할 때는 종종 봄을 사용해야합니다 ...

곡선 적분 변수 교체 : $ \ int_0^1 \ frac {y^2} {\ sqrt {1-y^2}} dy $ to $ \ int_0^{\ frac {\ pi} {2}} \ sin^2tdt $?곡선 적분 변수 교체 : $ \ int_0^1 \ frac {y^2} {\ sqrt {1-y^2}} dy $ to $ \ int_0^{\ frac {\ pi} {2}} \ sin^2tdt $?Apr 19, 2025 pm 03:03 PM

곡선 통합의 가변 대체에 대한 질문이 기사는 곡선 통합 계산에서 가변 대체 단계를 자세히 설명합니다. 질문자가 계산하고 있습니다 ...

WeChat 애플릿 응용 프로그램 : 서비스 계정과의 프로세스, 수수료 및 관계에 대한 자세한 설명?WeChat 애플릿 응용 프로그램 : 서비스 계정과의 프로세스, 수수료 및 관계에 대한 자세한 설명?Apr 19, 2025 pm 03:00 PM

신청 절차 및 WeChat 애플릿의 수수료에 대한 자세한 설명. 내 친구는 Wechat 애플릿 개발을 의뢰했습니다. 신청 과정에서 수수료 및 절차에 문제가 발생했습니다.

Java 캐시 데이터 손실 : 캐시에서 데이터를 검색 할 수없는 이유는 무엇입니까?Java 캐시 데이터 손실 : 캐시에서 데이터를 검색 할 수없는 이유는 무엇입니까?Apr 19, 2025 pm 02:57 PM

Java 프로젝트에서 Java 캐시 데이터를 얻을 수없는 이유에 대한 분석 및 최적화 솔루션은 빠른 액세스를 위해 많은 양의 데이터를 메모리로 캐시하는 것이 일반적입니다 ...

더 나은 Java 개발자가되고 싶다면 JVM의 어떤 측면이 가장 가치가 있습니까?
또는
Java Advanced : JVM에 대한 심층적 인 연구, 어떤 핵심 메커니즘이 가장 많이 탐색 할 가치가 있습니까?더 나은 Java 개발자가되고 싶다면 JVM의 어떤 측면이 가장 가치가 있습니까? 또는 Java Advanced : JVM에 대한 심층적 인 연구, 어떤 핵심 메커니즘이 가장 많이 탐색 할 가치가 있습니까?Apr 19, 2025 pm 02:54 PM

심층적 인 Java : 탐험 할 가치가있는 가상 기계 세계. 많은 Java 개발자들은 기본 구문과 일반적으로 사용되는 프레임 워크를 마스터 한 후 기술을 더욱 향상시키기를 희망합니다 ...

맵 트럭 도구를 통해 시스템 도킹에서 필드 매핑을 효율적으로 해결하는 방법은 무엇입니까?맵 트럭 도구를 통해 시스템 도킹에서 필드 매핑을 효율적으로 해결하는 방법은 무엇입니까?Apr 19, 2025 pm 02:48 PM

시스템 도킹의 필드 매핑 문제 및 솔루션. 시스템 도킹 프로세스 중에는 종종 한 시스템의 인터페이스 필드를 다른 시스템에 맵핑해야 할 필요성이 있습니다 ...

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

PhpStorm 맥 버전

PhpStorm 맥 버전

최신(2018.2.1) 전문 PHP 통합 개발 도구

WebStorm Mac 버전

WebStorm Mac 버전

유용한 JavaScript 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

SublimeText3 Linux 새 버전

SublimeText3 Linux 새 버전

SublimeText3 Linux 최신 버전

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse를 SAP NetWeaver 애플리케이션 서버와 통합합니다.