This presentation introduces some advanced concepts of threads, as implemented in the Java platform. It is part of a series of slides dedicated to threads. This slides introduces the following concepts:
- Callable
- Futures
- Executors and executor services
- Deadlocks (brief introduction)
The presentation is took from the Java course I run in the bachelor-level informatics curriculum at the University of Padova.
1. CONCURRENT PROGRAMMING
THREAD’S ADVANCED CONCEPTS
PROGRAMMAZIONE CONCORRENTE E DISTR.
Università degli Studi di Padova
Dipartimento di Matematica
Corso di Laurea in Informatica, A.A. 2015 – 2016
rcardin@math.unipd.it
3. Programmazione concorrente e distribuita
CALLABLES
A Callable is a Runnable, that returns a value
The Callable type is parametrized on the type of its
return value
Callable<Integer> represents an asynchronous
computation that will produce an Integer value
The value computed is not directly available
We need a type to represents a value that will be available in
the future...
Represents a deferred computation
3Riccardo Cardin
public interface Callable<V> {
// The method can throw an exception,
// unlike Runnable run method
public V call() throws Exception;
}
4. Programmazione concorrente e distribuita
FUTURES
A Future represents a computation whose
result will be available at some future time
Start the computation, give someone the Future
object, and forget about it
To obtain the result a synchronization is needed
The get method blocks until the result is available
Or until a timeout has been reached
4Riccardo Cardin
public interface Future<V> {
V get() throws . . .;
V get(long timeout, TimeUnit unit) throws . . .;
void cancel(boolean mayInterrupt);
boolean isCancelled();
boolean isDone();
}
5. Programmazione concorrente e distribuita
FUTURES
Using FutureTask is possible to run a
Callable, obtaining a Future as result
Adapter of the Runnable and Future interfaces
Using FutureTask is possible to run a Callable using
a Thread
Exception semantics
ExecutionException: error during execution
CancellationException: task was cancelled
5Riccardo Cardin
Callable<Integer> myComputation = . . .;
FutureTask<Integer> task = new FutureTask<Integer>(myComputation);
Thread t = new Thread(task); // it's a Runnable
t.start();
// . . .
Integer result = task.get(); // it's a Future
7. Programmazione concorrente e distribuita
FUTURES
A Future have some interesting characteristics
Immutable
Once a future is completed, it will be completed forever
Lets treat asynchronous programming in a
synchronous way
Simplify the division of complex task into smaller ones, that
can be executed concurrently
7Riccardo Cardin
Future<Integer> future = /* Initialization */ ;
System.out.println(future.get()); // Blocks and print 42
System.out.println(future.get()); // Prints 42 again
produceSomething
startDoingSomething
doSomethingWithResult
r
9. Programmazione concorrente e distribuita
EXECUTORS
Usually it doesn’t make sense to have a one-to-
one relationship between a task and a thread
Thread is a mechanism for execution a sequence of
instructions (task)
Creating a new thread means to ask some work to the OS, so
it is a time consuming operation
When tasks are short lived, run many of them on the
same thread
When tasks are computationally intensive, use one
thread per processor
Avoid the overhead of context switching among threads
Anyway, all that you need is a thread pool
9Riccardo Cardin
10. Programmazione concorrente e distribuita
EXECUTORS
Executors are implementation of thread pools
An homogeneous pool of worker threads
Amortizes thread creation and teardown
Improves responsiveness, due to lack of task execution’s delay
Thread pools execution using static factory methods
Each method return an executor instance that implements a
specific execution policy
10Riccardo Cardin
// Create the thread pool with a specified execution policy
Executor executor = Executors.newCachedThreadPool();
Runnable hellos = new Runnable() { /* Say hello a lot of times */ };
Runnable goodbyes =
new Runnable() {/* Say hello a lot of times */ };
// Submit task for execution to thread pool
executors.execute(hellos);
executors.execute(goodbyes);
11. Programmazione concorrente e distribuita
EXECUTORS
An Executor executes tasks, choosing the
threads on which to run them
You have not the full control on thread life cycle
Based on the producer / consumer pattern
Activities produce tasks, threads consume tasks
Decoupling of task submission from task execution
Simplier changing of execution policy
What, where, when, and how of task execution
11Riccardo Cardin
Runnable task = new Runnable() { /* Some task */ };
Executor executor = // Get an instance to an executor
executor.execute(task); // A thread is choosen to execute the task
12. Programmazione concorrente e distribuita
EXECUTORS
Execution policies
Dependent on the available computing resources and
quality of service requirements
In what thread will tasks be executed?
In what order should tasks be executed (FIFO, LIFO, priority
order)?
How many tasks may execute concurrently?
How many tasks may be queued pending execution?
If a task has to be rejected because the system is overloaded,
which task should be selected as the victim, and how should
the application be notified?
What actions should be taken before or after executing a
task?
12Riccardo Cardin
13. Programmazione concorrente e distribuita
EXECUTORS
13Riccardo Cardin
Available executors policies
Method Description
newCachedThreadPool New thread are created as needed; idle
threads are kept for 60 seconds
newFixedThreadPool The pool contains a fixed set of threads;
idle threads are kept indefinitely
newSingleThreadExecutor A «pool» with a single thread that executes
the submitted tasks sequentially (similar to
the Swing event dispatch thread)
newScheduledThreadPool A fixed-thread pool for scheduled execution
newSingleThreadScheduledExecutor A single-thread «pool» for scheduled
execution
15. Programmazione concorrente e distribuita
EXECUTOR SERVICES
To execute a Callable, use an instance of the
ExecutorService interface
Previous static factory methods return such instances
1° submit returns a Future containing the task itself
Control of execution (call isDone, cancel, isCancelled)
2° submit acts like the first, but return result object
3° submit returns a Future of the result of the Callable task
Method invokeAll executes all the input Callables
15Riccardo Cardin
Future<?> submit(Runnable task)
Future<T> submit(Runnable task, T result)
Future<T> submit(Callable<T> task)
<T> List<Future<T>> invokeAll(Collection<? Extends Callable<T>>
task)
Tipicalworkflow
16. Programmazione concorrente e distribuita
EXECUTOR SERVICES
Executor lifecycle
Derived from the interface of ExecutorService type
16Riccardo Cardin
Running
Shutting
down
Terminated
Executors are created in running state.
In this state an executor accepts new tasks
and schedules them for execution
This state is reached after shutdown method
was called. No new task are accepted, but
previously submitted task are allowed to complete.
The shutdownNow method initiates an abrupt
shutdown: no queued task not yet begun is started
Once all task are completed, the executor
transitions to the terminated state
17. Programmazione concorrente e distribuita
DEADLOCKS
Multiple threads wait forever due to a cyclic
locking dependency
If threads are nodes and relations of dependency are
edges, a cyclic graph means to have a deadlock
The JVM cannot detect deadlock, differently from
database systems
17Riccardo Cardin
A
R1
B
R2
C
R3 Also known as deadly embrace:
A needs a resource R hold by B, B
a resource hold by C, an so on...
18. Programmazione concorrente e distribuita
DEADLOCKS
Deadlocks rarely manifest themeselves
immediatly (only in production under heavy load)
Four conditions have to hold simultaneously (Coffman
conditions)
Mutual exclusion: at least one resource must be held in a non-
shareable mode
Hold and wait: a process is currently holding at least one
resource and requesting additional resources
No preemption: a resource can be released only voluntarily
Circular wait: a process must be waiting for a resource which is
being held by another process, which in turn is waiting for the
first process to release the resource
18Riccardo Cardin