Beruflich Dokumente
Kultur Dokumente
Java Team
Concurrency
New in Java 5: java.util.concurrent
Thread Pools, Task Scheduling
Concurrent Collections
Atomic variables
Locks, Conditions, Synchronizers
Enhance scalability, performance,
readability and
thread safety of Java applications
Provide richer set of concurrency
Threads
Threads are expensive to create, can require
500K of memory during creation
Your threads spend a lot of time context-
switching, even if you have 10 processors
Whenever you want to start a thread, don’t use
Threads:
use Executor
Disadvantage of using
Threads
Creating a new thread causes some
performance overhead .
Too many threads can lead to reduced
performance, as the CPU needs to switch
between these threads.
You cannot easily control the number of
threads, therefore you may run into out of
memory errors due to too many threads.
Why Concurrency?
wait(), notify(), and synchronize are
hard to use, specified at a low level,
can lead to poor performance
Lots of wheel reinventing
Reduced programming effort
Increased performance
Increased reliability
> Eliminate threading hazards such
as deadlock, starvation,
race conditions, or excessive
Goal of Concurrency
Do what Collections did for data structures
Allow development of thread-safe classes, such
as servlets, built on concurrent building blocks
(like ConcurrentHashMap)
Make some solved things easier for
masses
Make very hard things solvable by
experts
Concurrency Utilities
Task Scheduling Framework
Callable's and Future's
Synchronizers
Concurrent Collections
Atomic Variables
Locks
Nanosecond-granularity timing
Concurrency:
Task Scheduling
Framework
Task Scheduling
Framework
Executor/ExercuteService/Executors
framework supports
> standardizing invocation
> scheduling
> execution
> control of asynchronous tasks according to
a set of execution Policies
Executor is an interface
ExecutorService extends Executor
Why Prefer Executor?
Executor framework allows for a variety of
execution policies
Provides cancellation and shutdown support
Created via factory
Can customize shutdown hooks
Simpler interface
provides a way of de-coupling task
submission from the execution
Many Executor implementations impose some
sort of
Task Scheduling
(Executor)
Use anExecutor.execute(aRunnable)
Do NOT use new Thread(aRunnable).start()
try
Executer interface
Executor, a simple interface that supports
launching new tasks.
ExecutorService, a subinterface of Executor,
which adds features that help manage the
lifecycle, both of the individual tasks and of the
executor itself.
ScheduledExecutorService, a subinterface of
ExecutorService, supports future and/or periodic
execution of tasks.
Executor Interface
functions
execute(Runnable command)
Executes the given command at some time in
the future.
Executor and
ExecutorService
ExecutorService adds lifecycle
management
public interface Executor
{
void execute(Runnable command);
}
public interface ExecutorService extends
Executor
{
void shutdown();
Executor Service
ExecutorService supports graceful and
immediate shutdown
Has a lifecycle
Has many useful utility methods
Can get a single threaded executor
Bad Example: Webserver in a while() loop
listens forever and starts a new thread
for each request.
Executor Service
Methods
submit(Callable<T> task)
Submits a value-returning task for execution
and returns a Future representing the pending
results of the task.
submit(Runnable task)
Submits a Runnable task for execution and
returns a Future representing that task.
submit(Runnable task, T result)
Submits a Runnable task for execution and
returns a Future representing that task that will
upon completion return the given result.
Creating ExecutorService From
Executors
public class Executors
{
static ExecutorService newSingleThreadedExecutor();
static ExecutorService newFixedThreadPool(int n);
static ExecutorService newCachedThreadPool(int n);
static ScheduledExecutorService
newScheduledThreadPool(int n);
// additional versions specifying ThreadFactory
// additional utility methods
}
Using Executor
Executor pool =
Executor.newFixedThreadPool(7);
…socket.accept(); …
Runnable r = new Runnable() {
//handle request
}
pool.execute();
pre-J2SE 5.0 Code
Web
classServer—poor
WebServer resource management
{
public static void main(String[] args)
{
ServerSocket socket = new
ServerSocket(80);
while (true) {
final Socket connection =
socket.accept();
Runnable r = new Runnable() {
Executors Example
Web Server—better resource management
class WebServer
{
Executor pool
=Executors.newFixedThreadPool(7);
public static void main(String[] args)
{
ServerSocket socket = new
ServerSocket(80);
while (true) {
final Socket connection =
ScheduledExecutorService
final ScheduledFuture<?>
beeperHandle =
scheduler.scheduleAtFixedRate(beeper,
10, 10, SECONDS);
scheduler.schedule(new Runnable()
{
Functions
schedule(Callable<V> callable, long delay,
TimeUnit unit)
Creates and executes a ScheduledFuture that
becomes enabled after the given delay.
scheduleAtFixedRate(Runnable command,
long initialDelay, long period, TimeUnit unit)
Creates and executes a periodic action that
becomes enabled first after the given initial
delay, and subsequently with the given period;
scheduleWithFixedDelay(Runnable
command, long initialDelay, long delay,
Concurrency:Callables
and Futures
Callable's and
Future's:
If a new thread (callable thread) is started in an
Problem
application, there(pre-J2SE
is currently no way to return
a result from that thread to the thread (calling
5.0)
thread) that started it without the use of a
shared variable and appropriate synchronization
> This is complex and makes code harder to
understand and maintain
Interface Callable
Functional analog of Runnable.
It is similar to Runnable, in that both are
designed for classes whose instances are
potentially executed by another thread. A
Runnable, however, does not return a result
and cannot throw a checked exception.
public interface Callable<V>
{
V call() throws Exception;
}
Callables and Futures
Callable thread (Callee) implements Callable
interface
> Implement call() method rather than run()
Calling thread (Caller) submits Callable object to
Executor and then moves on
> Through submit() not execute()
> The submit() returns a Future object
Calling thread (Caller) then retrieves the result
using get() method of Future object
> If result is ready, it is returned
Runnable vs Callable
Runnable Callable