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 设置的边界自动调整池大小 #getPoolSize
(见 #getCorePoolSize
)和 maximumPoolSize(见 #getMaximumPoolSize
)。
在方法 #execute(Runnable)
中提交新任务时,如果运行的线程少于 corePoolSize 线程,则会创建一个新线程来处理请求,即使其他工作线程处于空闲状态。 否则,如果运行的线程数少于 maximumPoolSize 线程,则仅当队列已满时,才会创建一个新线程来处理请求。 通过设置 corePoolSize 和 maximumPoolSize 相同,可以创建固定大小的线程池。 通过将 maximumPoolSize 设置为本质上未绑定的值(例如 Integer.MAX_VALUE
),允许池容纳任意数量的并发任务。 大多数情况下,核心和最大池大小仅在构造时设置,但它们也可能动态使用 #setCorePoolSize
和 #setMaximumPoolSize
更改。 </dd>
<dt>按需构造</dt>
<>默认情况下,即使核心线程最初创建且仅在新任务到达时启动,但可以使用方法#prestartCoreThread
或#prestartAllCoreThreads
方法动态重写。 如果使用非空队列构造池,可能需要预先启动线程。 </dd>
<dt>创建新线程</dt>
<dd>新线程是使用 a ThreadFactory
. 如果未指定,则使用 a Executors#defaultThreadFactory
,用于创建线程以全部处于同 ThreadGroup
一状态,并且具有相同的 NORM_PRIORITY
优先级和非守护程序状态。 通过提供不同的 ThreadFactory,可以更改线程的名称、线程组、优先级、守护程序状态等。 ThreadFactory
如果在从中返回 null newThread
时无法创建线程,执行程序将继续执行,但可能无法执行任何任务。 线程应具有“modifyThread”。 RuntimePermission
如果使用池的工作线程或其他线程不具有此权限,服务可能会降级:配置更改可能无法及时生效,关闭池可能处于可能但无法完成的状态。</dd>
<dt>Keep-alive times</dt>
<dd>如果池当前超过 corePoolSize 线程,如果线程已空闲超过 keepAliveTime(请参阅 #getKeepAliveTime(TimeUnit)
)。 这提供了在池未主动使用时减少资源消耗的方法。 如果池稍后变得更加活跃,则会构造新线程。 也可以使用方法 #setKeepAliveTime(long, TimeUnit)
动态更改此参数。 使用有效值 Long.MAX_VALUE
TimeUnit#NANOSECONDS
可禁用空闲线程在关闭之前终止。 默认情况下,仅当存在多个 corePoolSize 线程时,保留活动策略才适用,但方法 #allowCoreThreadTimeOut(boolean)
也可用于将此超时策略应用于核心线程,只要 keepAliveTime 值为非零。 </dd>
<dt>队列</dt>
<dd>Any BlockingQueue
可用于转移和保存提交的任务。 此队列的使用与池大小调整进行交互:
<ul>
<li>如果运行的线程数少于 corePoolSize 线程,则执行程序始终更喜欢添加新线程而不是队列。
<li>如果 corePoolSize 或更多线程正在运行,则执行程序始终更喜欢对请求进行排队,而不是添加新线程。
<li>如果请求无法排队,则会创建一个新线程,除非这将超过 maximumPoolSize,在这种情况下,任务将被拒绝。
</ul>
队列有三种常规策略: <ol>
<li><em> Direct handoffs.</em> 对于工作队列来说,一个良好的默认选择是将 SynchronousQueue
任务移交给线程,而不会保留这些任务。 在这里,如果没有线程立即可用于运行任务,则尝试对任务进行排队会失败,因此将构造一个新线程。 处理可能具有内部依赖项的请求集时,此策略可避免锁定。 直接交接通常需要无限的 maximumPoolSize,以避免拒绝新的提交任务。 这反过来又承认,当命令平均到达速度比可以处理快时,可能会有无限线程增长的可能性。
<li><em> Unbounded queues.</em> 使用未绑定的队列(例如 LinkedBlockingQueue
没有预定义容量的队列)将导致所有 corePoolSize 线程繁忙时在队列中等待新任务。 因此,将不再创建 corePoolSize 线程。 (因此 maximumPoolSize 的值没有任何影响。当每个任务完全独立于其他任务时,这可能很合适,因此任务不会影响彼此的执行:例如,在网页服务器中。 虽然这种排队方式在平滑暂时性请求突发方面很有用,但它承认当命令继续以比处理平均快的速度到达时,工作队列增长的可能性是无限的。
<li><em>Bounded queues.</em> 绑定队列(例如,a ArrayBlockingQueue
)有助于防止资源耗尽,当与有限的 maximumPoolSizes 一起使用时,但可能更难以优化和控制。 队列大小和最大池大小可能会相互权衡:使用大型队列和小型池可最大程度地减少 CPU 使用率、OS 资源和上下文切换开销,但可能会导致人为的低吞吐量。 如果任务频繁阻止(例如,如果它们受 I/O 绑定),则系统可能能够计划线程的时间超过你允许的线程数。 使用小型队列通常需要更大的池大小,这使得 CPU 更加繁忙,但可能会遇到不可接受的计划开销,这也会降低吞吐量。
</老>
</dd>
<dt>拒绝的任务</dt>
<>当执行程序关闭时,在方法#execute(Runnable)
中提交的新任务将 <em>rejected</em>,当执行程序对最大线程和工作队列容量使用有限边界并且饱和时也是如此。 在任一情况下,该方法 execute
都 RejectedExecutionHandler#rejectedExecution(Runnable, ThreadPoolExecutor)
调用其 RejectedExecutionHandler
方法。 提供了四个预定义的处理程序策略:
<老>
<li>在默认值 ThreadPoolExecutor.AbortPolicy
中,处理程序在拒绝时引发运行时 RejectedExecutionException
。
<li>In ThreadPoolExecutor.CallerRunsPolicy
,调用 execute
自身的线程运行任务。 这提供了一个简单的反馈控制机制,可降低提交新任务的速率。
<li>In ThreadPoolExecutor.DiscardPolicy
,无法执行的任务只会被删除。 此策略仅用于那些从未依赖任务完成的罕见情况。
<li>In ThreadPoolExecutor.DiscardOldestPolicy
,如果执行程序未关闭,则删除工作队列的头任务,然后重试执行(这可能会再次失败,导致重复此操作)。此策略很少被接受。 在几乎所有情况下,还应取消该任务,以便在任何组件中导致异常等待其完成,以及/或记录失败,如文档中所示 ThreadPoolExecutor.DiscardOldestPolicy
。
</老>
可以定义和使用其他类型的 RejectedExecutionHandler
类。 这样做需要一些谨慎,尤其是当策略设计为仅在特定容量或排队策略下工作时。 </dd>
<dt>Hook 方法</dt>
<dd>此类提供 protected
可 #beforeExecute(Thread, Runnable)
替代方法, #afterExecute(Runnable, Throwable)
这些方法在执行每个任务之前和之后调用。 这些可用于操作执行环境;例如,重新初始化 ThreadLocals、收集统计信息或添加日志条目。 此外,可以重写方法 #terminated
以执行在执行程序完全终止后需要执行的任何特殊处理。
如果挂钩、回调或 BlockingQueue 方法引发异常,则内部工作线程可能会反过来失败、突然终止并可能替换。</dd>
<dt>队列维护</dt>
<dd>方法 #getQueue()
允许访问工作队列,以便进行监视和调试。 强烈建议不要将此方法用于任何其他目的。 提供两种方法, #remove(Runnable)
当 #purge
大量排队任务被取消时,可用于协助存储填海。</dd>
<dt>填海</dt>
<dd>:在程序 <em>AND</em> 中不再引用的池没有剩余线程可以回收(垃圾回收),而不会显式关闭。 可以使用零核线程和/或设置 #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) |
|
ThreadPoolExecutor(Int32, Int32, Int64, TimeUnit, IBlockingQueue, IRejectedExecutionHandler) |
|
ThreadPoolExecutor(Int32, Int32, Int64, TimeUnit, IBlockingQueue, IThreadFactory) |
|
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 支持 Mono for Android 基础结构,不打算直接从代码使用。 |
ThresholdType |
此 API 支持 Mono for Android 基础结构,不打算直接从代码使用。 |
方法
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() |
使当前线程等待,直到唤醒它,通常是通过 em 通知/em> 或 <em>interrupted</em>。<>< (继承自 Object) |
Wait(Int64) |
使当前线程等待直到唤醒,通常是通过 <em>通知</em> 或 <em interrupted</em>>,或直到经过一定数量的实时。 (继承自 Object) |
Wait(Int64, Int32) |
使当前线程等待直到唤醒,通常是通过 <em>通知</em> 或 <em interrupted</em>>,或直到经过一定数量的实时。 (继承自 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) |
使用 |