Back>
8.1 Implicit couplings between tasks and execution policies.
Some tasks have characteristics that require or preclude a specific execution policy. Tasks that depend on other tasks require that the thread pool be large enough that tasks are never queued or rejected; tasks that exploit thread confinement require sequential execution. Document these requirements so that future maintainers do not undermine safety or liveness by substituting an incompatible execution policy.
Whenever you submit to an Executor tasks that are not independent, by aware of the possibility of thread starvation deadlock, and document any pool sizing or configuration constraints in the code or configuration file where the Executor is configured.
The following example illustrates thread starvation deadlock.
Example
8.2 Sizing thread pools
Ncpu = number of CPUs = Runtime.getRuntime().availableProcessors()
Ucpu = target CPU utilization, [0,1]
W/C = ratio of wait time to compute time
Nthreads = Ncpu x Ucpu x ( 1 + W/C)
8.3 Configuring ThreadPoolExecutor
The newCachedthreadPool factory is a good default choice for an Executor, providing better queuing performance than a fixed thread pool. A fixed size thread pool is a good choice when you need to limit the number of concurrent tasks for resource-management purposes, as in a server application that accepts requests from network clients and would otherwise be vulnerable to overload.
There is no predefined statuation policy to make execute block when the work queue is full. Hoever, using a Semaphore, we can bound the task injection rate. The following example shows this technique.
BoundedExecutor.java
Thread pool create new thread through ThreadFactory's newThread method . ThreadFactory is customizable, as illustrated in the following example.
MyThreadFactory.java
8.4 Extending ThreadPoolExecutor
ThreadPoolExecutor can be extended in order to override the beforeExecute, afterExecute and terminated hooks. The following is an example.
TimingThreadPool.java
8.5 Parallelizing recursive algorithms
Sequential loop iterations are suitable for parallelization when each iteration is independent of the others and the work done in each iteration of the loop body is significant enough to offset the cost of managing a new task.
The following is an example for transforming sequential process to parallel one.
TransformingSequential.java
The following example is a puzzle solving framework with parallel route searching.
PuzzleSolver.java