ThreadPoolExecutor 클래스
정의
중요
일부 정보는 릴리스되기 전에 상당 부분 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적이거나 묵시적인 보증도 하지 않습니다.
ExecutorService
일반적으로 팩터리 메서드를 사용하여 Executors
구성된 여러 풀된 스레드 중 하나를 사용하여 제출된 각 작업을 실행하는 작업입니다.
[Android.Runtime.Register("java/util/concurrent/ThreadPoolExecutor", DoNotGenerateAcw=true)]
public class ThreadPoolExecutor : Java.Util.Concurrent.AbstractExecutorService
[<Android.Runtime.Register("java/util/concurrent/ThreadPoolExecutor", DoNotGenerateAcw=true)>]
type ThreadPoolExecutor = class
inherit AbstractExecutorService
- 상속
- 파생
- 특성
설명
ExecutorService
일반적으로 팩터리 메서드를 사용하여 Executors
구성된 여러 풀된 스레드 중 하나를 사용하여 제출된 각 작업을 실행하는 작업입니다.
스레드 풀은 일반적으로 작업당 호출 오버헤드 감소로 인해 많은 수의 비동기 작업을 실행할 때 향상된 성능을 제공하고, 태스크 컬렉션을 실행할 때 사용되는 스레드를 포함하여 리소스를 경계하고 관리하는 수단을 제공합니다. 또한 완료 ThreadPoolExecutor
된 작업 수와 같은 몇 가지 기본 통계도 유지 관리합니다.
다양한 컨텍스트에서 유용하게 사용할 수 있도록 이 클래스는 다양한 조정 가능한 매개 변수와 확장성 후크를 제공합니다. 그러나 프로그래머는 가장 일반적인 사용 시나리오에 대한 설정을 미리 구성하는 보다 편리한 Executors
팩터리 메서드 Executors#newCachedThreadPool
(바인딩되지 않은 스레드 풀, 자동 스레드 매립), Executors#newFixedThreadPool
(고정 크기 스레드 풀) 및 Executors#newSingleThreadExecutor
(단일 백그라운드 스레드)를 사용해야 합니다. 그렇지 않으면 이 클래스를 수동으로 구성하고 튜닝할 때 다음 가이드를 사용합니다.
<dl>
<dt>Core 및 최대 풀 크기</dt>
<dd>A ThreadPoolExecutor
는 corePoolSize(참조) 및 maximumPoolSize(참조#getCorePoolSize
)로 설정된 범위에 따라 풀 크기(참조#getPoolSize
#getMaximumPoolSize
)를 자동으로 조정합니다.
메서드 #execute(Runnable)
에서 새 작업이 제출될 때 corePoolSize 스레드보다 적은 수의 스레드가 실행 중인 경우 다른 작업자 스레드가 유휴 상태인 경우에도 요청을 처리하기 위해 새 스레드가 만들어집니다. 그렇지 않으면 최대 풀 크기보다 작은 스레드가 실행 중인 경우 큐가 가득 찬 경우에만 요청을 처리하기 위해 새 스레드가 만들어집니다. corePoolSize 및 maximumPoolSize를 동일하게 설정하여 고정 크기 스레드 풀을 만듭니다. maximumPoolSize를 기본적으로 바인딩되지 않은 값(예: )으로 Integer.MAX_VALUE
설정하면 풀이 임의의 수의 동시 작업을 수용할 수 있습니다. 대부분의 경우 코어 및 최대 풀 크기는 생성 시에만 설정되지만 동적으로 사용 #setCorePoolSize
및 #setMaximumPoolSize
변경될 수도 있습니다. </dd>
<dt>주문형 생성</dt>
<dd>기본적으로 코어 스레드도 처음에는 새 작업이 도착하는 경우에만 생성되고 시작되지만 메서드 또는 #prestartAllCoreThreads
를 #prestartCoreThread
사용하여 동적으로 재정의할 수 있습니다. 비어있지 않은 큐를 사용하여 풀을 생성하는 경우 스레드를 미리 시작하려고 할 수 있습니다. </dd>
<dt>새 스레드 만들기</dt>
<dd>새 스레드는 .를 ThreadFactory
사용하여 만들어집니다. 달리 지정 Executors#defaultThreadFactory
하지 않으면 스레드가 모두 동일한 ThreadGroup
우선 순위 및 NORM_PRIORITY
비데몬 상태인 스레드를 만드는 데 사용됩니다. 다른 ThreadFactory를 제공하여 스레드 이름, 스레드 그룹, 우선 순위, 디먼 상태 등을 변경할 수 있습니다. nullnewThread
을 ThreadFactory
반환하여 요청할 때 스레드를 만들지 못하는 경우 실행기는 계속되지만 태스크를 실행하지 못할 수 있습니다. 스레드에는 "modifyThread" RuntimePermission
가 있어야 합니다. 풀을 사용하는 작업자 스레드 또는 다른 스레드에 이 권한이 없는 경우 서비스가 저하될 수 있습니다. 구성 변경 내용이 적시에 적용되지 않을 수 있으며 종료 풀은 종료가 가능하지만 완료되지 않은 상태로 유지될 수 있습니다.</dd>
<dt>연결 유지 시간</dt>
<dd>풀에 현재 corePoolSize 스레드보다 많은 스레드가 있는 경우 keepAliveTime보다 많은 유휴 상태인 경우 초과 스레드가 종료됩니다(참조 #getKeepAliveTime(TimeUnit)
). 이렇게 하면 풀이 적극적으로 사용되지 않을 때 리소스 소비를 줄일 수 있습니다. 나중에 풀이 더 활성화되면 새 스레드가 생성됩니다. 이 매개 변수는 메서드 #setKeepAliveTime(long, TimeUnit)
를 사용하여 동적으로 변경할 수도 있습니다. 값을 Long.MAX_VALUE
TimeUnit#NANOSECONDS
사용하면 종료하기 전에 유휴 스레드가 종료되는 것을 효과적으로 비활성화할 수 있습니다. 기본적으로 keep-alive 정책은 corePoolSize 스레드보다 많은 경우에만 적용되지만 keepAliveTime 값이 0이 아닌 한 이 시간 제한 정책을 코어 스레드에도 적용하는 데 메서드 #allowCoreThreadTimeOut(boolean)
를 사용할 수 있습니다. </dd>
<dt>Queuing</dt>
<dd>제출된 작업을 전송하고 보유하는 데 Any BlockingQueue
를 사용할 수 있습니다. 이 큐의 사용은 풀 크기 조정과 상호 작용합니다.
<ul>
<li>corePoolSize 스레드보다 적은 수의 스레드가 실행 중인 경우 실행기는 항상 큐보다 새 스레드를 추가하는 것을 선호합니다.
<li>corePoolSize 또는 더 많은 스레드가 실행 중인 경우 실행기는 항상 새 스레드를 추가하는 대신 요청을 큐에 대기하는 것을 선호합니다.
<li>요청을 큐에 대기할 수 없는 경우 maximumPoolSize를 초과하지 않는 한 새 스레드가 만들어지며, 이 경우 작업이 거부됩니다.
</ul>
큐에 대한 세 가지 일반적인 전략이 있습니다. <ol>
<li><em> 직접 핸드오프.</em> 작업 큐 SynchronousQueue
에 대한 좋은 기본 선택은 그렇지 않으면 유지하지 않고 스레드에 작업을 전달하는 것입니다. 여기서는 즉시 실행할 수 있는 스레드가 없으면 작업을 큐에 대기시키려고 시도하면 실패하므로 새 스레드가 생성됩니다. 이 정책은 내부 종속성이 있을 수 있는 요청 집합을 처리할 때 잠금을 방지합니다. 직접 전달에는 일반적으로 새로 제출된 작업의 거부를 방지하기 위해 무제한 maximumPoolSize가 필요합니다. 그러면 명령이 처리할 수 있는 것보다 평균적으로 더 빠르게 도착할 때 바인딩되지 않은 스레드 증가 가능성이 인정됩니다.
<li><em> Unbounded 큐.</em> 바인딩되지 않은 큐(예: LinkedBlockingQueue
미리 정의된 용량이 없는 큐)를 사용하면 모든 corePoolSize 스레드가 사용 중일 때 새 작업이 큐에서 대기하게 됩니다. 따라서 corePoolSize 스레드는 생성되지 않습니다. (따라서 maximumPoolSize의 값은 아무런 영향을 미치지 않습니다.) 이 작업은 각 태스크가 다른 작업과 완전히 독립적일 때 적절할 수 있으므로 태스크가 다른 작업 실행에 영향을 줄 수 없습니다. 예를 들어 웹 페이지 서버에서 이 큐 스타일은 일시적인 요청 버스트를 부드럽게 하는 데 유용할 수 있지만 명령이 처리할 수 있는 것보다 평균적으로 더 빠르게 도착할 때 바인딩되지 않은 작업 큐 증가 가능성을 인정합니다.
<li><em>Bounded queues.</em> 제한된 큐(예: a ArrayBlockingQueue
)는 한정된 maximumPoolSize와 함께 사용할 때 리소스 소모를 방지하는 데 도움이 되지만 튜닝 및 제어가 더 어려울 수 있습니다. 큐 크기와 최대 풀 크기는 서로 절판될 수 있습니다. 큰 큐와 작은 풀을 사용하면 CPU 사용량, OS 리소스 및 컨텍스트 전환 오버헤드를 최소화하지만 인위적으로 처리량이 낮아질 수 있습니다. 작업이 자주 차단되는 경우(예: I/O 바인딩된 경우) 시스템은 사용자가 허용하지 않는 것보다 많은 스레드에 대한 시간을 예약할 수 있습니다. 작은 큐를 사용하려면 일반적으로 풀 크기가 커야 하므로 CPU가 더 바쁘게 유지되지만 허용할 수 없는 일정 오버헤드가 발생할 수 있으므로 처리량도 감소합니다.
</ol>
</dd>
<dt>거부된 작업</dt>
<dd>메서드#execute(Runnable)
><<에서 제출된 새 태스크는 실행기가 종료된 경우 및 실행기가 최대 스레드 및 작업 큐 용량 모두에 대해 유한 범위를 사용하고 포화 상태에 있을 때 거부됩니다.> 두 경우 모두 메서드는 execute
해당 RejectedExecutionHandler
메서드의 메서드를 RejectedExecutionHandler#rejectedExecution(Runnable, ThreadPoolExecutor)
호출합니다. 4개의 미리 정의된 처리기 정책이 제공됩니다.
<ol>
<li>기본값 ThreadPoolExecutor.AbortPolicy
에서 처리기는 거부 시 런타임 RejectedExecutionException
을 throw합니다.
<li>In ThreadPoolExecutor.CallerRunsPolicy
- 자체 호출하는 스레드가 작업을 실행합니다 execute
. 이렇게 하면 새 작업이 제출되는 속도를 늦출 수 있는 간단한 피드백 제어 메커니즘이 제공됩니다.
<li>In ThreadPoolExecutor.DiscardPolicy
, 실행할 수 없는 작업은 단순히 삭제됩니다. 이 정책은 작업 완료에 의존하지 않는 드문 경우에만 설계되었습니다.
<li>In ThreadPoolExecutor.DiscardOldestPolicy
- 실행기가 종료되지 않으면 작업 큐의 머리에서 작업이 삭제된 다음 실행이 다시 시도됩니다(다시 실패할 수 있으므로 반복될 수 있습니다.) 이 정책은 거의 허용되지 않습니다. 거의 모든 경우에 작업을 취소하여 완료를 기다리는 모든 구성 요소에서 예외를 발생시키고 설명서에 설명된 ThreadPoolExecutor.DiscardOldestPolicy
대로 오류를 기록해야 합니다.
</ol>
다른 종류의 RejectedExecutionHandler
클래스를 정의하고 사용할 수 있습니다. 이렇게 하려면 정책이 특정 용량 또는 큐 정책에서만 작동하도록 설계된 경우에 특히 주의해야 합니다. </dd>
<dt>Hook 메서드</dt>
<dd>이 클래스는 각 작업의 실행 전후에 호출되는 재정의 가능한 #beforeExecute(Thread, Runnable)
#afterExecute(Runnable, Throwable)
메서드와 메서드를 제공합니다protected
. 실행 환경을 조작하는 데 사용할 수 있습니다. 예를 들어 ThreadLocals를 다시 초기화하거나, 통계를 수집하거나, 로그 항목을 추가합니다. 또한 실행기가 완전히 종료된 후 수행해야 하는 특수 처리를 수행하도록 메서드 #terminated
를 재정의할 수 있습니다.
후크, 콜백 또는 BlockingQueue 메서드가 예외를 throw하는 경우 내부 작업자 스레드가 차례로 실패하고 갑자기 종료되고 대체될 수 있습니다.</dd>
<dt>큐 유지 관리</dt>
<dd>메서드 #getQueue()
를 사용하면 모니터링 및 디버깅을 위해 작업 큐에 액세스할 수 있습니다. 다른 용도로 이 메서드를 사용하는 것은 권장되지 않습니다. 제공된 두 가지 방법이며 #purge
많은 #remove(Runnable)
수의 대기 중인 작업이 취소될 때 스토리지 매립을 지원할 수 있습니다.</dd>
<dt>Reclamation</dt>
<dd>프로그램 <em>AND</em> 에서 더 이상 참조되지 않는 풀에는 명시적으로 종료하지 않고 남은 스레드를 회수(가비지 수집)할 수 있습니다. 0코어 스레드 및/또는 설정 #allowCoreThreadTimeOut(boolean)
의 하한을 사용하여 적절한 연결 유지 시간을 설정하여 사용하지 않는 모든 스레드가 최종적으로 사망할 수 있도록 풀을 구성할 수 있습니다. </dd>
</dl>
<b>확장 예제입니다.</b> 이 클래스의 대부분의 확장은 보호된 후크 메서드 중 하나 이상을 재정의합니다. 예를 들어 간단한 일시 중지/다시 시작 기능을 추가하는 하위 클래스는 다음과 같습니다.
{@code
class PausableThreadPoolExecutor extends ThreadPoolExecutor {
private boolean isPaused;
private ReentrantLock pauseLock = new ReentrantLock();
private Condition unpaused = pauseLock.newCondition();
public PausableThreadPoolExecutor(...) { super(...); }
protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
pauseLock.lock();
try {
while (isPaused) unpaused.await();
} catch (InterruptedException ie) {
t.interrupt();
} finally {
pauseLock.unlock();
}
}
public void pause() {
pauseLock.lock();
try {
isPaused = true;
} finally {
pauseLock.unlock();
}
}
public void resume() {
pauseLock.lock();
try {
isPaused = false;
unpaused.signalAll();
} finally {
pauseLock.unlock();
}
}
}}
1.5에 추가되었습니다.
에 대한 java.util.concurrent.ThreadPoolExecutor
Java 설명서
이 페이지의 일부는 Android 오픈 소스 프로젝트에서 만들고 공유하고 Creative Commons 2.5 특성 라이선스에 설명된 용어에 따라 사용되는 작업을 기반으로 하는 수정 사항입니다.
생성자
ThreadPoolExecutor(Int32, Int32, Int64, TimeUnit, IBlockingQueue) |
지정된 초기 매개 변수, Executors#defaultThreadFactory 기본 스레드 팩터리 및 ThreadPoolExecutor를 사용하여 새 |
ThreadPoolExecutor(Int32, Int32, Int64, TimeUnit, IBlockingQueue, IRejectedExecutionHandler) |
지정된 초기 매개 변수와 Executors#defaultThreadFactory 기본 스레드 팩터리를 사용하여 새 |
ThreadPoolExecutor(Int32, Int32, Int64, TimeUnit, IBlockingQueue, IThreadFactory) |
지정된 초기 매개 변수와 ThreadPoolExecutor를 사용하여 새 |
ThreadPoolExecutor(Int32, Int32, Int64, TimeUnit, IBlockingQueue, IThreadFactory, IRejectedExecutionHandler) |
지정된 초기 매개 변수를 사용하여 새 |
ThreadPoolExecutor(IntPtr, JniHandleOwnership) |
JNI 개체의 관리되는 표현을 만들 때 사용되는 생성자입니다. 런타임에서 호출합니다. |
속성
ActiveCount |
작업을 적극적으로 실행하는 대략적인 스레드 수를 반환합니다. |
Class |
이 |
CompletedTaskCount |
실행을 완료한 대략적인 총 작업 수를 반환합니다. |
CorePoolSize |
코어 스레드 수를 반환합니다. -또는- 코어 스레드 수를 설정합니다. |
Handle |
기본 Android 인스턴스에 대한 핸들입니다. (다음에서 상속됨 Object) |
IsShutdown |
|
IsTerminated |
|
IsTerminating |
이 실행기가 종료 중이거나 |
JniIdentityHashCode |
|
JniPeerMembers |
|
LargestPoolSize |
풀에 동시에 있었던 가장 많은 수의 스레드를 반환합니다. |
MaximumPoolSize |
허용되는 최대 스레드 수를 반환합니다. -또는- 허용되는 최대 스레드 수를 설정합니다. |
PeerReference |
|
PoolSize |
풀의 현재 스레드 수를 반환합니다. |
Queue |
이 실행기에서 사용하는 작업 큐를 반환합니다. |
RejectedExecutionHandler |
검색할 수 없는 작업에 대한 현재 처리기를 반환합니다. -또는- 검색할 수 없는 작업에 대한 새 처리기를 설정합니다. |
TaskCount |
실행이 예약된 대략적인 총 작업 수를 반환합니다. |
ThreadFactory |
새 스레드를 만드는 데 사용되는 스레드 팩터리를 반환합니다. -또는- 새 스레드를 만드는 데 사용되는 스레드 팩터리를 설정합니다. |
ThresholdClass |
이 API는 Android용 Mono 인프라를 지원하며 코드에서 직접 사용할 수 없습니다. |
ThresholdType |
이 API는 Android용 Mono 인프라를 지원하며 코드에서 직접 사용할 수 없습니다. |
메서드
AfterExecute(IRunnable, Throwable) |
지정된 Runnable의 실행이 완료될 때 호출되는 메서드입니다. |
AllowCoreThreadTimeOut(Boolean) |
새 태스크가 도착할 때 필요한 경우 대체되는 유지 시간 내에 작업이 도착하지 않을 경우 코어 스레드가 시간 초과되고 종료될 수 있는지 여부를 제어하는 정책을 설정합니다. |
AllowsCoreThreadTimeOut() |
이 풀에서 코어 스레드가 시간 초과를 허용하고 keepAlive 시간 내에 작업이 도착하지 않으면 종료할 수 있는 경우 true를 반환하며, 새 태스크가 도착할 때 필요한 경우 대체됩니다. |
AwaitTermination(Int64, TimeUnit) |
|
AwaitTerminationAsync(Int64, TimeUnit) |
|
BeforeExecute(Thread, IRunnable) |
지정된 스레드에서 지정된 Runnable을 실행하기 전에 호출된 메서드입니다. |
Clone() |
이 개체의 복사본을 만들고 반환합니다. (다음에서 상속됨 Object) |
Dispose() |
|
Dispose(Boolean) |
|
Equals(Object) |
다른 개체가 이 개체와 "같음"인지 여부를 나타냅니다. (다음에서 상속됨 Object) |
Execute(IRunnable) |
나중에 지정된 작업을 실행합니다. |
GetHashCode() |
개체에 대한 해시 코드 값을 반환합니다. (다음에서 상속됨 Object) |
GetKeepAliveTime(TimeUnit) |
스레드가 종료되기 전에 유휴 상태로 유지될 수 있는 시간인 스레드 연결 유지 시간을 반환합니다. |
InvokeAll(ICollection) |
|
InvokeAll(ICollection, Int64, TimeUnit) |
|
InvokeAny(ICollection) |
|
InvokeAny(ICollection, Int64, TimeUnit) |
|
JavaFinalize() |
가비지 수집에서 개체에 대한 참조가 더 이상 없다고 판단할 때 개체의 가비지 수집기에서 호출됩니다. (다음에서 상속됨 Object) |
NewTaskFor(ICallable) |
|
NewTaskFor(IRunnable, Object) |
|
Notify() |
이 개체의 모니터에서 대기 중인 단일 스레드를 해제합니다. (다음에서 상속됨 Object) |
NotifyAll() |
이 개체의 모니터에서 대기 중인 모든 스레드를 해제합니다. (다음에서 상속됨 Object) |
PrestartAllCoreThreads() |
모든 핵심 스레드를 시작하여 작업을 유휴 상태로 기다립니다. |
PrestartCoreThread() |
코어 스레드를 시작하여 작업을 유휴 상태로 기다립니다. |
Purge() |
취소된 모든 |
Remove(IRunnable) |
실행기가 있는 경우 실행기 내부 큐에서 이 작업을 제거하므로 아직 시작되지 않은 경우 실행되지 않습니다. |
SetHandle(IntPtr, JniHandleOwnership) |
Handle 속성을 설정합니다. (다음에서 상속됨 Object) |
SetKeepAliveTime(Int64, TimeUnit) |
스레드가 종료되기 전에 유휴 상태로 유지될 수 있는 시간인 스레드 연결 유지 시간을 설정합니다. |
Shutdown() |
이전에 제출한 태스크가 실행되는 순서대로 종료를 시작하지만 새 작업은 허용되지 않습니다. |
ShutdownNow() |
현재 실행 중인 모든 작업을 중지하고, 대기 중인 태스크의 처리를 중지하고, 실행을 기다리고 있던 작업 목록을 반환합니다. |
Submit(ICallable) |
|
Submit(IRunnable) |
실행을 위해 실행 가능한 태스크를 제출하고 해당 작업을 나타내는 Future를 반환합니다. (다음에서 상속됨 AbstractExecutorService) |
Submit(IRunnable, Object) |
|
Terminated() |
실행기가 종료될 때 호출되는 메서드입니다. |
ToArray<T>() |
|
ToString() |
개체의 문자열 표현을 반환합니다. (다음에서 상속됨 Object) |
UnregisterFromRuntime() |
|
Wait() |
현재 스레드가 각성될 때까지 대기하게 하며, 일반적으로 <알림을 받<>거나 <><중단/종료>합니다.> (다음에서 상속됨 Object) |
Wait(Int64) |
현재 스레드가 각성될 때까지 대기하게 하며, 일반적으로 <>알림을 받<거나 <중단/>종료><>하거나 일정량의 실시간 경과가 발생할 때까지 대기합니다. (다음에서 상속됨 Object) |
Wait(Int64, Int32) |
현재 스레드가 각성될 때까지 대기하게 하며, 일반적으로 <>알림을 받<거나 <중단/>종료><>하거나 일정량의 실시간 경과가 발생할 때까지 대기합니다. (다음에서 상속됨 Object) |
명시적 인터페이스 구현
IJavaPeerable.Disposed() |
|
IJavaPeerable.DisposeUnlessReferenced() |
|
IJavaPeerable.Finalized() |
|
IJavaPeerable.JniManagedPeerState |
|
IJavaPeerable.SetJniIdentityHashCode(Int32) |
|
IJavaPeerable.SetJniManagedPeerState(JniManagedPeerStates) |
|
IJavaPeerable.SetPeerReference(JniObjectReference) |
|
확장 메서드
JavaCast<TResult>(IJavaObject) |
Android 런타임 확인 형식 변환을 수행합니다. |
JavaCast<TResult>(IJavaObject) |
|
GetJniTypeName(IJavaPeerable) |
|
AwaitTerminationAsync(IExecutorService, Int64, TimeUnit) |
|
InvokeAnyAsync(IExecutorService, ICollection) |
|
InvokeAnyAsync(IExecutorService, ICollection, Int64, TimeUnit) |
|