您的位置:首页 > 其它

JCIP-6-Task Execution

2016-02-25 10:46 281 查看
6-Task Execution

6.1-Executing tasks in threads

6.1.1. Executing Tasks Sequentially

6.1.2. Explicitly Creating Threads for Tasks

6.1.3. Disadvantages of Unbounded Thread Creation

Thread lifecycle overhead. Thread creation and teardown are not free

Resource consumption. When there are more runnable

threads than available processors, threads sit idle.Having many idle threads can tie up a lot of memory.

Stability. it is far easier to structure your program to avoid hitting this limit.Up to a certain point, more threads can improve throughput, but beyond that point creating more threads just slows

down your application

On 32-bit machines, a major limiting factor is address space for thread stacks. Each thread maintains two execution stacks, one for Java code

and one for native code.

6.2-The Executor framework

6.2.1. Example: Web Server Using Executor

java.util.concurrent provides a flexible thread

pool implementation as part of the Executor framework.

It provides a standard means of decoupling task

submission from task execution, describing tasks with Runnable.

Using

an Executor is usually the easiest path to implementing a producer-consumer design in your application.

6.2.2. Execution Policies

An execution policy specifies the “what, where, when, and

how” of task execution

Whenever you see code of the form:new Thread(runnable).start() seriously consider replacing it with the use

of an Executor.

6.2.3. Thread Pools

newFixedThreadPool

keep the pool size constant (adding new threads if a thread dies

newCachedThreadPool

add new threads when demand increases

newSingleThreadExecutor

replacing it if it dies unexpectedly.

newScheduledThreadPool

A fixed-size thread pool that supports delayed and periodic task execution

6.2.4. Executor Lifecycle

But the JVM can’t exit until all the (non-daemon) threads have terminated,so failing to

shut down an Executor could prevent the JVM from exiting.

The lifecycle implied by ExecutorService has three states: running, shutting down, and terminated. The shutdownNow method initiates an abrupt shutdown: it attempts to cancel outstanding tasks and

does not start any tasks that are queued but not begun.

You can wait for an ExecutorService to reach the terminated state with awaitTermination, It is common to follow shutdown immediately by awaitTermination, creating

the effect of synchronously shutting down the ExecutorService.

6.2.5. Delayed and Periodic Tasks

The Timer facility manages the execution of deferred and periodic tasks. However, Timer has some drawbacks, and ScheduledThreadPoolExecutor should be thought of as its

replacement.

Timer does have support for scheduling based on absolute, not relative time, so that tasks can be sensitive to changes in the system clock;

ScheduledThreadPoolExecutor supports only relative time.

A Timer creates only a single thread for executing timer tasks.Scheduled

thread pools address this limitation by letting you provide multiple threads for executing deferred and periodic tasks.

so an unchecked exception thrown from a TimerTask terminates the timer thread. Timer

also doesn’t resurrect the thread in this situation; instead, it erroneously assumes the entire Timer was cancelled. ScheduledThreadPoolExecutor deals

properly with ill-behaved tasks; there is little reason to use Timer in Java 5.0 or later.

DelayQueue, a BlockingQueue implementation that provides the scheduling functionality of

ScheduledThreadPoolExecutor.

6.3-Finding exploitable parallelism

6.3.1. Example: Sequential Page Renderer

6.3.2. Result-bearing Tasks: Callable and Future

Runnable is a fairly limiting abstraction; run

cannot return a value or throw checked exceptions.

For these types of tasks, Callable is a better abstraction: it expects that the main

entry point, call, will return a value and anticipates that it might throw an exception.

To express a non-value-returning task with Callable, use Callable.

a task executed by an Executor has four phases: created, submitted,

started, and completed.

Future represents the lifecycle of a task and provides methods to test whether the task has completed or been

cancelled, retrieve its result, and cancel the task.

Future.get:It returns immediately or

throws an Exception if the task has already completed, but if not it blocks until the task completes.If get throws ExecutionException, the underlying exception can be retrieved with

getCause.

Future.get deals with two possible problems: that the task encountered an Exception, or the thread

calling get was interrupted before the results were available.

6.3.3. Example: Page Renderer with Future

6.3.4. Limitations of Parallelizing Heterogeneous Tasks

6.3.5. CompletionService: Executor Meets BlockingQueue

CompletionService combines the functionality of an Executor and a BlockingQueue. You can submit Callable tasks

to it for execution and use the queue-like methods take and poll to retrieve completed results, packaged as Futures,

as they become available. ExecutorCompletionService implements CompletionService, delegating the computation

to an Executor.

When a task is submitted, it is wrapped with a QueueingFuture, a subclass of FutureTask that overrides

done to place the result on the BlockingQueue,

6.3.6. Example: Page Renderer with CompletionService

6.3.7. Placing Time Limits on Tasks

The timed version of Future.get supports this

requirement: it returns as soon as the result is ready, but throws TimeoutException if the result is not ready within the

timeout period.

if a timed get completes with a TimeoutException, you can cancel the task through the

Future.

6.3.8. Example: A Travel Reservations Portal

The invokeAll method takes a collection of tasks and returns a collection of Futures. The two collections have

identical structures; invokeAll adds the Futures to the returned collection in the order imposed by the task collection’s

iterator, thus allowing the caller to associate a Future with the Callable it represents.

Summary

The

Executor framework permits you to decouple task submission from execution policy and supports a rich variety of

execution policies; whenever you find yourself creating threads to perform tasks, consider using an Executor instead.

To maximize the benefit of decomposing an application into tasks, you must identify sensible task boundaries.

Summary

6.1-Executing tasks in threads

6.1.1. Executing Tasks Sequentially

6.1.2. Explicitly Creating Threads for Tasks

6.1.3. Disadvantages of Unbounded Thread Creation

Thread lifecycle overhead. Thread creation and teardown are not free

Resource consumption. When there are more runnable

threads than available processors, threads sit idle.Having many idle threads can tie up a lot of memory.

Stability. it is far easier to structure your program to avoid hitting this limit.Up to a certain point, more threads can improve throughput, but beyond that point creating more threads just slows

down your application

On 32-bit machines, a major limiting factor is address space for thread stacks. Each thread maintains two execution stacks, one for Java code

and one for native code.

6.2-The Executor framework

6.2.1. Example: Web Server Using Executor

java.util.concurrent provides a flexible thread

pool implementation as part of the Executor framework.

It provides a standard means of decoupling task

submission from task execution, describing tasks with Runnable.

Using

an Executor is usually the easiest path to implementing a producer-consumer design in your application.

6.2.2. Execution Policies

An execution policy specifies the “what, where, when, and

how” of task execution

Whenever you see code of the form:new Thread(runnable).start() seriously consider replacing it with the use

of an Executor.

6.2.3. Thread Pools

newFixedThreadPool

keep the pool size constant (adding new threads if a thread dies

newCachedThreadPool

add new threads when demand increases

newSingleThreadExecutor

replacing it if it dies unexpectedly.

newScheduledThreadPool

A fixed-size thread pool that supports delayed and periodic task execution

6.2.4. Executor Lifecycle

But the JVM can’t exit until all the (non-daemon) threads have terminated,so failing to

shut down an Executor could prevent the JVM from exiting.

The lifecycle implied by ExecutorService has three states: running, shutting down, and terminated. The shutdownNow method initiates an abrupt shutdown: it attempts to cancel outstanding tasks and

does not start any tasks that are queued but not begun.

You can wait for an ExecutorService to reach the terminated state with awaitTermination, It is common to follow shutdown immediately by awaitTermination, creating

the effect of synchronously shutting down the ExecutorService.

6.2.5. Delayed and Periodic Tasks

The Timer facility manages the execution of deferred and periodic tasks. However, Timer has some drawbacks, and ScheduledThreadPoolExecutor should be thought of as its

replacement.

Timer does have support for scheduling based on absolute, not relative time, so that tasks can be sensitive to changes in the system clock;

ScheduledThreadPoolExecutor supports only relative time.

A Timer creates only a single thread for executing timer tasks.Scheduled

thread pools address this limitation by letting you provide multiple threads for executing deferred and periodic tasks.

so an unchecked exception thrown from a TimerTask terminates the timer thread. Timer

also doesn’t resurrect the thread in this situation; instead, it erroneously assumes the entire Timer was cancelled. ScheduledThreadPoolExecutor deals

properly with ill-behaved tasks; there is little reason to use Timer in Java 5.0 or later.

DelayQueue, a BlockingQueue implementation that provides the scheduling functionality of

ScheduledThreadPoolExecutor.

6.3-Finding exploitable parallelism

6.3.1. Example: Sequential Page Renderer

6.3.2. Result-bearing Tasks: Callable and Future

Runnable is a fairly limiting abstraction; run

cannot return a value or throw checked exceptions.

For these types of tasks, Callable is a better abstraction: it expects that the main

entry point, call, will return a value and anticipates that it might throw an exception.

To express a non-value-returning task with Callable, use Callable.

a task executed by an Executor has four phases: created, submitted,

started, and completed.

Future represents the lifecycle of a task and provides methods to test whether the task has completed or been

cancelled, retrieve its result, and cancel the task.

Future.get:It returns immediately or

throws an Exception if the task has already completed, but if not it blocks until the task completes.If get throws ExecutionException, the underlying exception can be retrieved with

getCause.

Future.get deals with two possible problems: that the task encountered an Exception, or the thread

calling get was interrupted before the results were available.

6.3.3. Example: Page Renderer with Future

6.3.4. Limitations of Parallelizing Heterogeneous Tasks

6.3.5. CompletionService: Executor Meets BlockingQueue

CompletionService combines the functionality of an Executor and a BlockingQueue. You can submit Callable tasks

to it for execution and use the queue-like methods take and poll to retrieve completed results, packaged as Futures,

as they become available. ExecutorCompletionService implements CompletionService, delegating the computation

to an Executor.

When a task is submitted, it is wrapped with a QueueingFuture, a subclass of FutureTask that overrides

done to place the result on the BlockingQueue,

6.3.6. Example: Page Renderer with CompletionService

6.3.7. Placing Time Limits on Tasks

The timed version of Future.get supports this

requirement: it returns as soon as the result is ready, but throws TimeoutException if the result is not ready within the

timeout period.

if a timed get completes with a TimeoutException, you can cancel the task through the

Future.

6.3.8. Example: A Travel Reservations Portal

The invokeAll method takes a collection of tasks and returns a collection of Futures. The two collections have

identical structures; invokeAll adds the Futures to the returned collection in the order imposed by the task collection’s

iterator, thus allowing the caller to associate a Future with the Callable it represents.

Summary

The

Executor framework permits you to decouple task submission from execution policy and supports a rich variety of

execution policies; whenever you find yourself creating threads to perform tasks, consider using an Executor instead.

To maximize the benefit of decomposing an application into tasks, you must identify sensible task boundaries.

Summary

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: