線程池-執(zhí)行機(jī)制ThreadPoolExecutor官方文檔

1.接口和抽象類的說(shuō)明

1.1 Executor

An object that executes submitted Runnable tasks. This interface 
provides a way of decoupling task submission from the 
mechanics of how each task will be run, including details of 
thread use, scheduling, etc. An Executor is normally used instead 
of explicitly creating threads. For example, rather than invoking 
new Thread(new(RunnableTask())).start() for each of a set of 
tasks, you might use

執(zhí)行提交的Runnable任務(wù)。此接口提供了將任務(wù)提交與任務(wù)運(yùn)行機(jī)制(包括線程使用、調(diào)度等)分離的方法。通常使用Executor而不是顯式創(chuàng)建線程。

 Executor executor = anExecutor;
 executor.execute(new RunnableTask1());
 executor.execute(new RunnableTask2());

1.2 ExecutorService

An Executor that provides methods to manage termination and 
methods that can produce a Future for tracking progress of one 
or more asynchronous tasks.

An ExecutorService can be shut down, which will cause it to 
reject new tasks. Two different methods are provided for shutting 
down an ExecutorService. The shutdown() method will allow 
previously submitted tasks to execute before terminating, while 
the shutdownNow() method prevents waiting tasks from starting 
and attempts to stop currently executing tasks. Upon termination, 
an executor has no tasks actively executing, no tasks awaiting 
execution, and no new tasks can be submitted. An unused 
ExecutorService should be shut down to allow reclamation of its 
resources.

Method submit extends base method 
Executor.execute(Runnable) by creating and returning a Future 
that can be used to cancel execution and/or wait for completion. 
Methods invokeAny and invokeAll perform the most commonly 
useful forms of bulk execution, executing a collection of tasks and 
then waiting for at least one, or all, to complete. (Class 
ExecutorCompletionService can be used to write customized 
variants of these methods.)

The Executors class provides factory methods for the executor 
services provided in this package.

提供更多方法的Executor:管理終止的方法,生成跟蹤一個(gè)或多個(gè)異步任務(wù)進(jìn)度的Future的方法。

ExecutorService可關(guān)閉,關(guān)閉后會(huì)拒絕新任務(wù)。兩種方法關(guān)閉:

  • shutdown()方法將允許先前提交的任務(wù)繼續(xù)執(zhí)行
  • shutdownNow()將阻止等待任務(wù)啟動(dòng)并嘗試停止當(dāng)前正在執(zhí)行的任務(wù)。

終止時(shí),沒(méi)有任何正在執(zhí)行的任務(wù),沒(méi)有等待執(zhí)行的任務(wù),也沒(méi)有任何新任務(wù)可提交。應(yīng)關(guān)閉未使用的ExecutorService以允許回收器資源。

submit方法擴(kuò)展自Executor.execute(Runnable),可以創(chuàng)建和返回一個(gè)Future以取消執(zhí)行或等待完成。invokeAny和invokeAll批量執(zhí)行任務(wù),執(zhí)行一組任務(wù),然后等待至少一個(gè)或全部完成。(ExecutorCompletionService可用于對(duì)這些方法進(jìn)行定制)。

如下是網(wǎng)絡(luò)服務(wù)的框架,線程池中的線程為請(qǐng)求提供服務(wù),使用預(yù)配置的Executors.newFixedThreadPool(int)工廠方法:

 class NetworkService implements Runnable {
   private final ServerSocket serverSocket;
   private final ExecutorService pool;

   public NetworkService(int port, int poolSize)
       throws IOException {
     serverSocket = new ServerSocket(port);
     pool = Executors.newFixedThreadPool(poolSize);
   }

   public void run() { // run the service
     try {
       for (;;) {
         pool.execute(new Handler(serverSocket.accept()));
       }
     } catch (IOException ex) {
       pool.shutdown();
     }
   }
 }

 class Handler implements Runnable {
   private final Socket socket;
   Handler(Socket socket) { this.socket = socket; }
   public void run() {
     // read and service request on socket
   }
 }

以下方法分兩個(gè)階段關(guān)閉ExecutorService,首先調(diào)用shutdown拒絕接收任務(wù),然后在必要時(shí)調(diào)用shutdownNow以取消還在執(zhí)行的任務(wù):

 void shutdownAndAwaitTermination(ExecutorService pool) {
   pool.shutdown(); // Disable new tasks from being submitted
   try {
     // Wait a while for existing tasks to terminate
     if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
       pool.shutdownNow(); // Cancel currently executing tasks
       // Wait a while for tasks to respond to being cancelled
       if (!pool.awaitTermination(60, TimeUnit.SECONDS))
           System.err.println("Pool did not terminate");
     }
   } catch (InterruptedException ie) {
     // (Re-)Cancel if current thread also interrupted
     pool.shutdownNow();
     // Preserve interrupt status
     Thread.currentThread().interrupt();
   }
 }

1.3 AbstractExecutorService

Provides default implementations of ExecutorService execution 
methods. This class implements the submit, invokeAny and 
invokeAll methods using a RunnableFuture returned by 
newTaskFor, which defaults to the FutureTask class provided in 
this package. For example, the implementation of 
submit(Runnable) creates an associated RunnableFuture that is 
executed and returned. Subclasses may override the newTaskFor 
methods to return RunnableFuture implementations other than 
FutureTask.

提供ExecutorService執(zhí)行方法的默認(rèn)實(shí)現(xiàn)。此類實(shí)現(xiàn)了submit、invokeAny及invokeAll方法,使用newTaskFor返回的RunnableFuture(默認(rèn)是FutureTask)。例如submit(Runnable) 創(chuàng)建、執(zhí)行并返回一個(gè)關(guān)聯(lián)的RunnableFuture。子類可以覆蓋newTaskFor 返回其他的RunnableFuture實(shí)現(xiàn)。

    protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
        return new FutureTask<T>(runnable, value);
    }

    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
        return new FutureTask<T>(callable);
    }
    public <T> Future<T> submit(Runnable task, T result) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task, result);
        execute(ftask);
        return ftask;
    }
    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
        throws InterruptedException {
        if (tasks == null)
            throw new NullPointerException();
        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
        boolean done = false;
        try {
            for (Callable<T> t : tasks) {
                RunnableFuture<T> f = newTaskFor(t);
                futures.add(f);
                execute(f);
            }
            for (int i = 0, size = futures.size(); i < size; i++) {
                Future<T> f = futures.get(i);
                if (!f.isDone()) {
                    try {
                        f.get();
                    } catch (CancellationException ignore) {
                    } catch (ExecutionException ignore) {
                    }
                }
            }
            done = true;
            return futures;
        } finally {
            if (!done)
                for (int i = 0, size = futures.size(); i < size; i++)
                    futures.get(i).cancel(true);
        }
    }

例如,下面使用CustomTask代替FutureTask:

 public class CustomThreadPoolExecutor extends ThreadPoolExecutor {

   static class CustomTask<V> implements RunnableFuture<V> {...}

   protected <V> RunnableFuture<V> newTaskFor(Callable<V> c) {
       return new CustomTask<V>(c);
   }
   protected <V> RunnableFuture<V> newTaskFor(Runnable r, V v) {
       return new CustomTask<V>(r, v);
   }
   // ... add constructors, etc.
 }

2.ThreadPoolExecutor

An ExecutorService that executes each submitted task using one 
of possibly several pooled threads, normally configured using 
Executors factory methods.

Thread pools address two different problems: they usually 
provide improved performance when executing large numbers of 
asynchronous tasks, due to reduced per-task invocation 
overhead, and they provide a means of bounding and managing 
the resources, including threads, consumed when executing a 
collection of tasks. Each ThreadPoolExecutor also maintains 
some basic statistics, such as the number of completed tasks.

To be useful across a wide range of contexts, this class provides 
many adjustable parameters and extensibility hooks. However, 
programmers are urged to use the more convenient Executors 
factory methods Executors.newCachedThreadPool() (unbounded 
thread pool, with automatic thread reclamation), 
Executors.newFixedThreadPool(int) (fixed size thread pool) and 
Executors.newSingleThreadExecutor() (single background 
thread), that preconfigure settings for the most common usage 
scenarios. Otherwise, use the following guide when manually 
configuring and tuning this class:

線程池解決了兩個(gè)不同的問(wèn)題:

  • 由于減少了每個(gè)任務(wù)的調(diào)用開銷,它們通常在執(zhí)行大量異步任務(wù)時(shí)提供更高的性能
  • 并且它們提供了一種綁定和管理資源(包括線程)的方法,這些資源用于執(zhí)行一組任務(wù)。每個(gè)ThreadPoolExecutor還維護(hù)一些基本統(tǒng)計(jì)信息,例如已完成任務(wù)的數(shù)量。

為了適用于各種上下文,該類提供了許多可調(diào)參數(shù)和可擴(kuò)展性的鉤子。但是,推薦程序員被使用更方便的Executors工廠方法Executors.newCachedThreadPool()(無(wú)界線程池,具有自動(dòng)線程回收),Executors.newFixedThreadPool(int)(固定大小線程池)和Executors.newSingleThreadExecutor()(單個(gè)線程)。否則,在手動(dòng)配置和調(diào)整此類時(shí),請(qǐng)參照以下指南:

2.1 Core and maximum pool sizes

A ThreadPoolExecutor will automatically adjust the pool size (see 
getPoolSize()) according to the bounds set by corePoolSize (see 
getCorePoolSize()) and maximumPoolSize (see 
getMaximumPoolSize()). When a new task is submitted in 
method execute(Runnable), and fewer than corePoolSize threads 
are running, a new thread is created to handle the request, even 
if other worker threads are idle. If there are more than 
corePoolSize but less than maximumPoolSize threads running, a 
new thread will be created only if the queue is full. By setting 
corePoolSize and maximumPoolSize the same, you create a 
fixed-size thread pool. By setting maximumPoolSize to an 
essentially unbounded value such as Integer.MAX_VALUE, you 
allow the pool to accommodate an arbitrary number of concurrent 
tasks. Most typically, core and maximum pool sizes are set only 
upon construction, but they may also be changed dynamically 
using setCorePoolSize(int) and setMaximumPoolSize(int).

ThreadPoolExecutor將根據(jù)corePoolSize(請(qǐng)參閱getCorePoolSize())和maximumPoolSize(請(qǐng)參閱getMaximumPoolSize())設(shè)置的邊界自動(dòng)調(diào)整池大?。ㄕ?qǐng)參閱getPoolSize())。

當(dāng)在方法execute(Runnable)中提交新任務(wù),并且運(yùn)行的線程少于corePoolSize時(shí),即使其他工作線程處于空閑狀態(tài),也會(huì)創(chuàng)建一個(gè)新線程來(lái)處理該請(qǐng)求。

如果多于corePoolSize但少于maximumPoolSize線程在運(yùn)行,則只有在隊(duì)列已滿時(shí)才會(huì)創(chuàng)建新線程。

通過(guò)設(shè)置相同的corePoolSize和maximumPoolSize,可以創(chuàng)建固定大小的線程池。 通過(guò)將maximumPoolSize設(shè)置為Integer.MAX_VALUE,可以允許池容納任意數(shù)量的并發(fā)任務(wù)。 最典型的情況是,核心和最大池大小僅在構(gòu)造時(shí)設(shè)置,但也可以使用setCorePoolSize(int)和setMaximumPoolSize(int)動(dòng)態(tài)更改。

2.2 On-demand construction

By default, even core threads are initially created and started only 
when new tasks arrive, but this can be overridden dynamically 
using method prestartCoreThread() or prestartAllCoreThreads(). 
You probably want to prestart threads if you construct the pool 
with a non-empty queue.

默認(rèn)情況下即使核心線程已經(jīng)初始化并創(chuàng)建,但也只有在新任務(wù)到達(dá)時(shí)才啟動(dòng)。

可以通過(guò)使用方法prestartCoreThread() 和prestartAllCoreThreads()改變。當(dāng)創(chuàng)建線程池的隊(duì)列為非空,可能需要預(yù)啟動(dòng)線程。

2.3 Creating new threads

New threads are created using a ThreadFactory. If not otherwise 
specified, a Executors.defaultThreadFactory() is used, that 
creates threads to all be in the same ThreadGroup and with the 
same NORM_PRIORITY priority and non-daemon status. By 
supplying a different ThreadFactory, you can alter the thread's 
name, thread group, priority, daemon status, etc. If a 
ThreadFactory fails to create a thread when asked by returning 
null from newThread, the executor will continue, but might not be 
able to execute any tasks. Threads should possess the 
"modifyThread" RuntimePermission. If worker threads or other 
threads using the pool do not possess this permission, service 
may be degraded: configuration changes may not take effect in a 
timely manner, and a shutdown pool may remain in a state in 
which termination is possible but not completed.

使用ThreadFactory創(chuàng)建新線程。 如果沒(méi)有另外指定,則使用Executors.defaultThreadFactory(),它創(chuàng)建的所有線程都在同一個(gè)ThreadGroup中并具有相同的NORM_PRIORITY優(yōu)先級(jí)和非守護(hù)進(jìn)程狀態(tài)。 通過(guò)提供不同的ThreadFactory,您可以更改線程的名稱、線程組、優(yōu)先級(jí)、守護(hù)程序狀態(tài)等。

如果ThreadFactory創(chuàng)建線程失敗,executor會(huì)繼續(xù)運(yùn)行,但是可能不會(huì)執(zhí)行任何任務(wù)。線程應(yīng)該擁有"modifyThread" RuntimePermission。如果使用池的工作線程或其他線程沒(méi)有該權(quán)限,服務(wù)可能會(huì)降級(jí):配置更改可能無(wú)法及時(shí)生效,并且關(guān)閉的池可能保持為完全終止的狀態(tài)。

2.4 Keep-alive times

If the pool currently has more than corePoolSize threads, excess 
threads will be terminated if they have been idle for more than the 
keepAliveTime (see getKeepAliveTime(TimeUnit)). This provides 
a means of reducing resource consumption when the pool is not 
being actively used. If the pool becomes more active later, new 
threads will be constructed. This parameter can also be changed 
dynamically using method setKeepAliveTime(long, TimeUnit). 
Using a value of Long.MAX_VALUE TimeUnit.NANOSECONDS 
effectively disables idle threads from ever terminating prior to 
shut down. By default, the keep-alive policy applies only when 
there are more than corePoolSize threads. But method 
allowCoreThreadTimeOut(boolean) can be used to apply this 
time-out policy to core threads as well, so long as the 
keepAliveTime value is non-zero.

如果池當(dāng)前有多于corePoolSize數(shù)量的線程,超過(guò)的線程如果空閑時(shí)間超過(guò)keepAliveTime就會(huì)終止(see getKeepAliveTime(TimeUnit))。這提供了一種當(dāng)池不是活躍使用情況下減少資源浪費(fèi)的方法。如果池隨后變得更活躍了,會(huì)創(chuàng)建新線程。該參數(shù)也可以動(dòng)態(tài)進(jìn)行修改(setKeepAliveTime(long, TimeUnit))。使用Long.MAX_VALUE TimeUnit.NANOSECONDS將使空閑線程不會(huì)終止。默認(rèn)情況下,keep-alive策略僅適用于多于corePoolSize的線程,但是allowCoreThreadTimeOut(boolean)方法可將超時(shí)策略應(yīng)用于核心線程,只要keepAliveTime值為非零。

2.5 Queuing

Any BlockingQueue may be used to transfer and hold submitted 
tasks. The use of this queue interacts with pool sizing:
* If fewer than corePoolSize threads are running, the Executor 
  always prefers adding a new thread rather than queuing.
* If corePoolSize or more threads are running, the Executor 
  always  prefers queuing a request rather than adding a new thread.
* If a request cannot be queued, a new thread is created unless 
  this would exceed maximumPoolSize, in which case, the task will 
  be rejected.

There are three general strategies for queuing:
1.Direct handoffs. A good default choice for a work queue is a 
  SynchronousQueue that hands off tasks to threads without 
  otherwise holding them. Here, an attempt to queue a task will fail 
  if no threads are immediately available to run it, so a new thread 
  will be constructed. This policy avoids lockups when handling 
  sets of requests that might have internal dependencies. Direct 
  handoffs generally require unbounded maximumPoolSizes to 
  avoid rejection of new submitted tasks. This in turn admits the 
  possibility of unbounded thread growth when commands continue 
  to arrive on average faster than they can be processed.

2.Unbounded queues. Using an unbounded queue (for example a 
  LinkedBlockingQueue without a predefined capacity) will cause 
  new tasks to wait in the queue when all corePoolSize threads are 
  busy. Thus, no more than corePoolSize threads will ever be 
  created. (And the value of the maximumPoolSize therefore 
  doesn't have any effect.) This may be appropriate when each 
  task is completely independent of others, so tasks cannot affect 
  each others execution; for example, in a web page server. While 
  this style of queuing can be useful in smoothing out transient 
  bursts of requests, it admits the possibility of unbounded work 
  queue growth when commands continue to arrive on average 
  faster than they can be processed.

3.Bounded queues. A bounded queue (for example, an 
  ArrayBlockingQueue) helps prevent resource exhaustion when 
  used with finite maximumPoolSizes, but can be more difficult to 
  tune and control. Queue sizes and maximum pool sizes may be 
  traded off for each other: Using large queues and small pools 
  minimizes CPU usage, OS resources, and context-switching 
  overhead, but can lead to artificially low throughput. If tasks 
  frequently block (for example if they are I/O bound), a system 
  may be able to schedule time for more threads than you 
  otherwise allow. Use of small queues generally requires larger 
  pool sizes, which keeps CPUs busier but may encounter 
  unacceptable scheduling overhead, which also decreases 
  throughput.

任何BlockingQueue都可用于傳送和保存提交的任務(wù)。隊(duì)列的使用與池大小相互作用:

  • 如果運(yùn)行的線程少于corePoolSize,則Executor會(huì)添加新線程而不是排隊(duì)。
  • 如果有corePoolSize或更多線程正在運(yùn)行,則Executor會(huì)讓人物排隊(duì)請(qǐng)求而不是添加新線程。
  • 如果請(qǐng)求無(wú)法排隊(duì),則會(huì)創(chuàng)建一個(gè)新線程,除非線程數(shù)超過(guò)maximumPoolSize,在這種情況下,該任務(wù)將被拒絕。

排隊(duì)有三種常規(guī)策略:

  • 直接交接。此種類型可以使用SynchronousQueue,它將任務(wù)交給線程而不另外保存它們。如果沒(méi)有線程立即可用于運(yùn)行人物,則嘗試對(duì)任務(wù)進(jìn)行排隊(duì)將失敗,因此將構(gòu)造新線程。此策略在處理可能具有內(nèi)部依賴性的請(qǐng)求集時(shí)避免了鎖定。直接交接通常需要無(wú)限制的maximumPoolSizes以避免拒絕新提交的任務(wù)。當(dāng)任務(wù)平均到達(dá)的速度快于它們被處理的速度時(shí),會(huì)導(dǎo)致無(wú)限制的線程數(shù)量增長(zhǎng)。
  • 無(wú)界隊(duì)列。使用無(wú)界隊(duì)列(例如未設(shè)置容量的LinkedBlockingQueue)會(huì)導(dǎo)致新任務(wù)進(jìn)入隊(duì)列等待,所有corePoolSize線程全部處于忙碌狀態(tài)。因此,不會(huì)有多于corePoolSize數(shù)量的線程。(maximumPoolSize 沒(méi)有任何意義)。當(dāng)每個(gè)任務(wù)完全獨(dú)立于其他任務(wù)時(shí),這可能是適合的,因此任務(wù)不會(huì)影響彼此的執(zhí)行。例如,網(wǎng)頁(yè)服務(wù)器。雖然這種排隊(duì)方式可以用于平滑請(qǐng)求的瞬時(shí)突發(fā),但當(dāng)命令繼續(xù)以比處理更快的速度到達(dá)時(shí),會(huì)導(dǎo)致工作隊(duì)列無(wú)限制的增長(zhǎng)。
  • 有界隊(duì)列。有限隊(duì)列(例如,ArrayBlockingQueue)在與maximumPoolSizes一起使用時(shí)有助于防止資源耗盡,但可能更難以調(diào)整和控制。隊(duì)列大小和最大池大小選擇是一種折中和權(quán)衡:
    1)使用大型隊(duì)列和小型池最小化CPU使用率、OS資源和上下文切換開銷,但可能導(dǎo)致人為的低吞吐量。如果任務(wù)經(jīng)常阻塞(例如,如果它們是I / O綁定的),系統(tǒng)可能能夠提供比您允許的更多線程的時(shí)間。
    2)使用小隊(duì)列通常需要更大的池大小,這會(huì)使CPU更加繁忙,但可能會(huì)遇到不可接受的調(diào)度開銷,這也會(huì)降低吞吐量。

2.6 Rejected tasks

New tasks submitted in method execute(Runnable) will be 
rejected when the Executor has been shut down, and also when 
the Executor uses finite bounds for both maximum threads and 
work queue capacity, and is saturated. In either case, the execute 
method invokes the 
RejectedExecutionHandler.rejectedExecution(Runnable, 
ThreadPoolExecutor) method of its RejectedExecutionHandler. 
Four predefined handler policies are provided:
1.In the default ThreadPoolExecutor.AbortPolicy, the handler 
  throws a runtime RejectedExecutionException upon rejection.
2.In ThreadPoolExecutor.CallerRunsPolicy, the thread that invokes 
  execute itself runs the task. This provides a simple feedback 
  control mechanism that will slow down the rate that new tasks are 
  submitted.
3.In ThreadPoolExecutor.DiscardPolicy, a task that cannot be 
  executed is simply dropped.
4.In ThreadPoolExecutor.DiscardOldestPolicy, if the executor is not 
  shut down, the task at the head of the work queue is dropped, 
  and then execution is retried (which can fail again, causing this to 
  be repeated.)

It is possible to define and use other kinds of 
RejectedExecutionHandler classes. Doing so requires some care 
especially when policies are designed to work only under 
particular capacity or queuing policies.

當(dāng)Executor關(guān)閉或已經(jīng)達(dá)到最大線程數(shù)量和隊(duì)列已滿時(shí),將拒絕execute(Runnable)提交的新任務(wù)。execute方法會(huì)調(diào)用其RejectedExecutionHandler的RejectedExecutionHandler.rejectedExecution(Runnable,ThreadPoolExecutor)方法。提供了四種預(yù)定義的處理程序策:

  • 1)在默認(rèn)的ThreadPoolExecutor.AbortPolicy中,處理程序在拒絕時(shí)拋出運(yùn)行時(shí)RejectedExecutionException。
  • 2)在ThreadPoolExecutor.CallerRunsPolicy中,調(diào)用execute本身的線程會(huì)運(yùn)行該任務(wù)。這提供了一種簡(jiǎn)單的反饋控制機(jī)制,可以降低新任務(wù)的提交速度。
  • 3)在ThreadPoolExecutor.DiscardPolicy中,簡(jiǎn)單地丟棄無(wú)法執(zhí)行的任務(wù)。
  • 4)在ThreadPoolExecutor.DiscardOldestPolicy中,如果 executor未關(guān)閉,則會(huì)刪除工作隊(duì)列頭部的任務(wù),然后重試執(zhí)行(可能會(huì)再次失敗,導(dǎo)致重復(fù)執(zhí)行此操作)。

可以定義和使用其他類型的RejectedExecutionHandler類。這樣做需要一些小心,特別是當(dāng)策略設(shè)計(jì)為僅在特定容量或排隊(duì)策略下工作時(shí)。

2.7 Hook methods

This class provides protected overridable beforeExecute(Thread, 
Runnable) and afterExecute(Runnable, Throwable) methods that 
are called before and after execution of each task. These can be 
used to manipulate the execution environment; for example, 
reinitializing ThreadLocals, gathering statistics, or adding log 
entries. Additionally, method terminated() can be overridden to 
perform any special processing that needs to be done once the 
Executor has fully terminated.

If hook or callback methods throw exceptions, internal worker 
threads may in turn fail and abruptly terminate.

此類提供了受保護(hù)的可重寫的beforeExecute(Thread, Runnable) 和 afterExecute(Runnable, Throwable),方法在每個(gè)任務(wù)執(zhí)行前和之后進(jìn)行調(diào)用??捎糜诓僮鲌?zhí)行環(huán)境,例如重新初始化ThreadLocals,收集統(tǒng)計(jì)信息或添加日志條目。另外,可以重寫terminated()方法以執(zhí)行當(dāng)Executor完全終止后需要執(zhí)行的任何特殊處理。

如果鉤子或回調(diào)方法拋出異常,內(nèi)部工作線程可能會(huì)失敗并突然終止。

2.8 Queue maintenance

Method getQueue() allows access to the work queue for 
purposes of monitoring and debugging. Use of this method for 
any other purpose is strongly discouraged. Two supplied 
methods, remove(Runnable) and purge() are available to assist in 
storage reclamation when large numbers of queued tasks 
become cancelled.

方法getQueue()允許訪問(wèn)工作隊(duì)列以進(jìn)行監(jiān)視和調(diào)試。強(qiáng)烈建議不要將此方法用于任何其他目的。當(dāng)大量排隊(duì)的任務(wù)被取消時(shí),方法remove(Runnable)和purge()可用于協(xié)助存儲(chǔ)回收。

2.9 Finalization

A pool that is no longer referenced in a program AND has no 
remaining threads will be shutdown automatically. If you would 
like to ensure that unreferenced pools are reclaimed even if users 
forget to call shutdown(), then you must arrange that unused 
threads eventually die, by setting appropriate keep-alive times, 
using a lower bound of zero core threads and/or setting 
allowCoreThreadTimeOut(boolean).

不再被引用并且沒(méi)有剩余線程的線程池將自動(dòng)關(guān)閉。如果希望確保即使用戶忘記調(diào)用shutdown()也會(huì)回收未引用的池,那么必須確保未使用的線程最終會(huì)死亡。這可以通過(guò)設(shè)置合適的keep-alive時(shí)間、使用0的核心線程數(shù),或者設(shè)置allowCoreThreadTimeOut(boolean)來(lái)實(shí)現(xiàn)。

2.10 示例

此類的大多數(shù)擴(kuò)展都會(huì)重寫一個(gè)或多個(gè)受保護(hù)的鉤子方法。 例如,這是一個(gè)添加簡(jiǎn)單暫停/恢復(fù)功能的子類

 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();
     }
   }
 }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容