JCIP-8-Applying Thread Pools

来源:互联网 发布:内置软件卸载大师 编辑:程序博客网 时间:2024/05/16 10:48

8-Applying Thread Pools

8.1. Implicit Couplings Between Tasks and Execution Policies

    *start*        ThreadLocal makes sense to use in pool threads only if the thread-local

value has a lifetime that is bounded by that of a task; Thread-Local should not be used in pool threads to communicate
values between tasks.
Mixing long-running and short-running tasks
risks “clogging” the pool unless it is very large; submitting tasks that depend on other tasks risks deadlock unless the
pool is unbounded.
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.
8.1.1. Thread Starvation Deadlock
Whenever you submit to an Executor tasks that are not independent, be 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.
8.1.2. Long-running Tasks
One technique that can mitigate the ill effects of long-running tasks is for tasks to use timed resource waits instead of
unbounded waits.
If a
thread pool is frequently full of blocked tasks, this may also be a sign that the pool is too small.

  • 8.2. Sizing Thread Pools

    For compute-intensive tasks, an NcpuͲprocessor system usually achieves optimum utilization with a thread pool of Ncpu

    +1 threads. (Even compute-intensive threads occasionally take a page fault or pause for some other reason, so an
    “extra” runnable thread prevents CPU cycles from going unused when this happens.
    int N_CPUS = Runtime.getRuntime().availableProcessors();

  • 8.3. Configuring ThreadPoolExecutor

    *8.3.1. Thread Creation and Teardown*    If the default execution policy does not meet your needs, you can instantiate a ThreadPoolExecutor through its

    constructor and customize it as you see fit; you can consult the source code for Executors to see the execution policies
    for the default configurations and use them as a starting point.
    A thread that has been idle for longer than the keep-alive time becomes a
    candidate for reaping and can be terminated if the current pool size exceeds the core size.
    When a ThreadPoolExecutor is initially created, the core threads are not started immediately but instead as tasks are submitted, unless
    you call prestartAllCoreThreads.
    8.3.2. Managing Queued Tasks
    There are three basic
    approaches to task queuing: unbounded queue, bounded queue, and synchronous handoff.
    SynchronousQueue is
    a practical choice only if the pool is unbounded or if rejecting excess tasks is acceptable. The newCachedThreadPool
    factory uses a SynchronousQueue.
    The newCachedThreadPool factory is a good default choice for an Executor, providing better queuing performance
    than a fixed thread pool.[5] 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.
    8.3.3. Saturation Policies
    The saturation policy for a
    ThreadPoolExecutor can be modified by calling setRejectedExecutionHandler.saturation policy: AbortPolicy,
    CallerRunsPolicy, DiscardPolicy, and DiscardOldestPolicy.
    8.3.4. Thread Factories
    8.3.5. Customizing ThreadPoolExecutor After Construction

  • 8.4. Extending ThreadPoolExecutor

    *8.4.1. Example: Adding Statistics to a Thread Pool*
  • 8.5. Parallelizing Recursive Algorithms

    *8.5.1. Example: A Puzzle Framework*

    Summary
    8.1. Implicit Couplings Between Tasks and Execution Policies
    start
    ThreadLocal makes sense to use in pool threads only if the thread-local
    value has a lifetime that is bounded by that of a task; Thread-Local should not be used in pool threads to communicate
    values between tasks.
    Mixing long-running and short-running tasks
    risks “clogging” the pool unless it is very large; submitting tasks that depend on other tasks risks deadlock unless the
    pool is unbounded.
    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.
    8.1.1. Thread Starvation Deadlock
    Whenever you submit to an Executor tasks that are not independent, be 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.
    8.1.2. Long-running Tasks
    One technique that can mitigate the ill effects of long-running tasks is for tasks to use timed resource waits instead of
    unbounded waits.
    If a
    thread pool is frequently full of blocked tasks, this may also be a sign that the pool is too small.
    8.2. Sizing Thread Pools
    For compute-intensive tasks, an NcpuͲprocessor system usually achieves optimum utilization with a thread pool of Ncpu
    +1 threads. (Even compute-intensive threads occasionally take a page fault or pause for some other reason, so an
    “extra” runnable thread prevents CPU cycles from going unused when this happens.
    int N_CPUS = Runtime.getRuntime().availableProcessors();
    8.3. Configuring ThreadPoolExecutor
    8.3.1. Thread Creation and Teardown
    If the default execution policy does not meet your needs, you can instantiate a ThreadPoolExecutor through its
    constructor and customize it as you see fit; you can consult the source code for Executors to see the execution policies
    for the default configurations and use them as a starting point.
    A thread that has been idle for longer than the keep-alive time becomes a
    candidate for reaping and can be terminated if the current pool size exceeds the core size.
    When a ThreadPoolExecutor is initially created, the core threads are not started immediately but instead as tasks are submitted, unless
    you call prestartAllCoreThreads.
    8.3.2. Managing Queued Tasks
    There are three basic
    approaches to task queuing: unbounded queue, bounded queue, and synchronous handoff.
    SynchronousQueue is
    a practical choice only if the pool is unbounded or if rejecting excess tasks is acceptable. The newCachedThreadPool
    factory uses a SynchronousQueue.
    The newCachedThreadPool factory is a good default choice for an Executor, providing better queuing performance
    than a fixed thread pool.[5] 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.
    8.3.3. Saturation Policies
    The saturation policy for a
    ThreadPoolExecutor can be modified by calling setRejectedExecutionHandler.saturation policy: AbortPolicy,
    CallerRunsPolicy, DiscardPolicy, and DiscardOldestPolicy.
    8.3.4. Thread Factories
    8.3.5. Customizing ThreadPoolExecutor After Construction
    8.4. Extending ThreadPoolExecutor
    8.4.1. Example: Adding Statistics to a Thread Pool
    8.5. Parallelizing Recursive Algorithms
    8.5.1. Example: A Puzzle Framework
    Summary
    DISSIDIA思维导图

0 0