SlideShare a Scribd company logo
Concurrent Programming in Java
Index
● Concurrency
● Threads
● Executors
● ForkJoin
● Paralell Streams
● CompletableFuture
● RXJava
● Actors
Concurrency?
„a property of systems in which
several computations are
executing simultaneously, and
potentially interacting with each
other“
http://en.wikipedia.org/wiki/Concurrency_(computer_science)
Why Concurrency?
Concurrency vs Paralellism
Paralell
Concurrent
context
switching
Amdahl's Law
The speedup of a program
using multiple processors
in parallel computing is
limited by the sequential
fraction of the program.
For example, if 95% of the program can be parallelized, the theoretical maximum speedup using parallel
computing would be 20× as shown in the diagram, no matter how many processors are used.
Concurrency
Paralellism
no
context
switch
context
switch
http://www.scanvine.com/source/daily-beasthttp://20minutosderisa.blogspot.co.at/
Java1.0 - Threads
public class TestRunnable implements Runnable {
public void run() {
//do something
}
}
Thread t = new Thread(new TestRunnable());
t.start(); //Thread starts
t.join(1000); //Waits 1 second until thread finishes
t.isAlive(); //checks if thread is alive
t.interrupt(); // stops thread
Communication betwen Threads
● Threads communicate by sharing access to
fields
● This kind of communication can lead to:
– Thread interference: sequence of steps overlap,
leading to wrong results.
– Memory consistency errors: changes to objects
are not immediatelly visible to other threads
Thread Interference
– sequence of
steps overlap,
leading to
wrong results
Memory Consistency Errors
//thread A increments counter
counter++;
// counter is shared by 2
threads
int counter = 0;
Thread A Thread B
//thread B prints out counter,
// right after A's change
System.out.println(counter);
Which value prints out B?
there's no guarantee that thread A's change to counter will be visible to thread B,
unless the programmer has established a happens-before relationship between these two statements
Threads
● To prevent Thread Interference and Memory
Consistency errors, we use synchronization,
that can introduce Thread Contention
– Deadlocks: threads wait for each other forever.
– Starvation: thread blocks for a long time, because
synchronized block takes too much time to execute.
– Livelocks: threads introduce logic to avoid
deadlocks, but they fail reapeatedly.
Deadlock
Thread Problems
● Expensive to create
– CPU + RAM (around. 512Kb per Thread!)
● Performance overhead when CPU does context switching (switching
between threads)
– Everytime a thread blocks or sleeps, context is switched
● Memory is shared around threads
– Problem with concurrent access to shared objects
● Difficult to control flow
● Difficult to control the number of threads started
● Locks to control access to shared resources
– Can introduce thread contention
Java5 – Concurrency
Enhancements
● Atomic Numbers (AtomicInteger): get and
increment a value atomically
● Concurrent Collections (e.g.
ConcurrentHashMap): supports concurrent
reads and updates
● ExecutorService
● Futures
ExecutorService
●
Takes care of executing (and controlling the execution) of asynchronous
tasks
●
Configurable Thread Pools
– CorePoolSize
– MaximumPoolSize,
– KeepAliveTime
– ThreadFactory
– RejectedExecutionHandler
● Predefined Executors
– Cached
– Fixed
– Scheduled
– SingleThreaded
http://blog.jessitron.com/2014/01/choosing-executorservice.html
Executor
Executor executor = new ThreadPoolExecutor(...)
executor.execute(new Runnable() {
public void run() {
//execute task
}
});
● Parent Interface of ExecutorService
● Just provides one method: execute
ExecutorService
//creates the executor service
ExecutorService executorService = Executors.newFixedThreadPool(5);
//submits a task to be executed asynchronously
Future<String> future = executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
return "hi";
}
});
//blocks until the result is ready
String message = future.get();
// no more executions will be accepted
executorService.shutdown();
// blocks until all tasks have completed execution
executorService.awaitTermination(1, TimeUnit.SECONDS);
ExecutorService + Callable + Future
//submits a task to be executed asynchronously
Future<String> future = executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
return "hi";
}
});
//blocks until the result is ready
String message = future.get();
Blocks until result is ready (thread has finished)
● Callable allows threads to return a result
● Future holds the result of the asynchronous computation
Future methods
● get()
– BLOCKS until result is ready
● get(timeout) throws TimeoutException
● cancel(mayInterruptIfRunning)
– If task has not started, it will not be started
– Otherwise, if mayInterruptIfRunning is true, it will Interrupt
● isDone()
● isCancelled()
ExecutorService – more methods
● List<Future> invokeAll(Collection <Callable> Tasks
– Executes all tasks, and returns when ALL have completed
execution
● Object invokeAny(Collection<Callable>)
– Starts execution of all tasks and returns the result of one finished
task. Tasks that have not completed, are cancelled.
● invoke* and await* methods support timeout parameters. If
task doesn't finish on time, method still returns
ExecutorService - Pros
● Now we can:
– Cache Threads => less overhead
– Control Size of Pool => less risk of OOM
– Easily retrieve values of asynchronous computation
(Future)
– Submit multiple tasks simultaneously
Executors - Cons
● How to control multiple executions?
Future<String> fA = executorService.submit(....);
Future<String> fB = executorService.submit(....);
Future<String> fC = executorService.submit(....);
String a = fA.get();
String b = fB.get();
String c = fC.get();
What if fB and fC are ready before fA?
Executors - Cons
● How to nest calls?
Future<String> fA = executorService.submit(new RemoteCall());
Future<String> fB = executorService.submit(new RemoveCallWithParam(fA.get());
…..........
String a = fA.get();
String a = fB.get();
fA.get()
BLOCKS!
Callbacks
executorService.execute(new RemoteCall(new Callback() {
public void notify(Object param) {
//remote call has finished – do something
}
}));
//continue doing something
interface Callback {
void notify(Object param);
}
class RemoteCall implements Runnable {
private Callback callback;
public RemoteCall(Callback callback) {
this.callback = callback;
}
public void run() {
//execute remote call
callback.notify(param)
}
}
when RemoteCall finishes
it notifies the registered callback
no
blocking
Executors - Cons
● Futures block and are difficult to nest
● Callbacks do not block, but do not solve the
problem of nested composition
Java7 - ForkJoin
● Implementation of ExecutorService
● Aims to utilize a multi-core architecture at a
maximum
● Uses a work-stealing algorithm: if a worker
runs out of tasks, can steal work from others
● Useful for recursive tasks
if (my portion of the work is small enough)
do the work directly
else
split my work into two pieces
invoke the two pieces and wait for the results
No Work-Stealing
http://dantravelling.wordpress.com/2012/03/02/short-haul-in-europe-sk547-cph-ams/
public class ForkSum extends RecursiveAction {
private final int[] array;
private final int start;
private final int end;
private final AtomicInteger result;
public ForkSum(int[] array, int start, int end, AtomicInteger result) {
super();
this.array = array;
this.start = start;
this.end = end;
this.result = result;
}
private void computeDirectly() {
int partialSum = 0;
for (int i = start; i < end; i++) {
partialSum += array[i];
}
result.addAndGet(partialSum);
}
@Override
protected void compute() {
if ((start - end) < 10) {
computeDirectly();
} else {
int delta = (end - start) / 2;
ForkSum a = new ForkSum(array, start, start + delta, result);
ForkSum b = new ForkSum(array, start + delta + 1, end, result);
invokeAll(a, b);
}
}
int[] array = new int[2046];
Arrays.fill(array, 2);
AtomicInteger result = new AtomicInteger(0);
ForkSum forkSum = new ForkSum(array, 0, array.length, result);
ForkJoinPool pool = new ForkJoinPool();
pool.invoke(forkSum);
System.out.println(forkSum.getResult());
ForkJoinPool uses work stealing
We can set the „parallelism level“ to ForkJoinPool
(defaults to number of processors)
Java7 - ForkJoin
● Only really useful for recursive tasks
● Does not help with the problems with had in the
Executors (blocking & nested composition)
Java8 – Streams
// PROBLEM: Perform a time-intensive computation
// to each element of the list
List<Integer> col = Arrays.asList(1, 2, 3);
// Procedural Solution
List<Integer> colResult = new ArrayList<Integer>();
for (Integer i : col) {
colResult.add(expensiveOperation(i));
}
//Functional Solution: use map() with a HighOrderFunction
List<Integer> colResultF =
col.stream().map(i -> expensiveOperation(i))
.collect(Collectors.toList());
Java8 – Parallel Streams
//Functional Solution+:
// parallelize the stream
// and use map() with a HighOrderFunction
List<Integer> colResultFP =
col.parallelStream().map(i -> expensiveOperation(i))
.collect(Collectors.toList());
Java8 - CompletableFuture
● Futures with
– Callbacks
– Transformations
– Possibility to explicitly set a value in the Future (i.e.
Promise)
Completing a CompletableFuture
//CALLEE
public CompletableFuture<String> doSomething() {
final CompletableFuture<String> future = createFuture();
// do something (synch or asynch)
// when ready, call
future.complete("hi");
// that will unlock the clients waiting for the future
return future;
}
//CALLER
CompletableFuture<String> cf = doSomething();
// Blocks until callee „completes“ the future with f.complete
String result = cf.get();
will normally be executed asynch
blocks
How to get a value from a
CompletableFuture
● get()
– BLOCKS until the value is present, and returns it
● get(timeout, timeoutUnit)
– BLOCKS until the value is present, or the timeout has been
reached. If the later , a TimeoutException is thrown
● getNow(valueIfAbsent)
– Doesn't block! if the value is present, it returns it; otherwise,
the valueIfAbsent param (default) is returned
How to complete a
CompletableFuture
● complete(value)
– completes ok with the value
– only the first call takes effect – subsequent calls are
ignored
● completeExceptionally(ex)
– completes with exception
– get() will throw an exception in the caller
● cancel()
– completes with a CancellationException
Completing a CompletableFuture
● Why is this useful?
– We can execute a task sometimes in synchronous,
and sometimes in asynchronous mode, without
having to change the client. We just deliver a
CompletableFuture, and the implementation
decides the execution mode.
Creating a CompletableFuture
// <Java7
CompletableFuture<String> f = CompletableFuture.supplyAsync( new Supplier<String>() {
@Override
public String get() {
// perform task
return "hi";
}
}, executorService);
// OR Using Lambdas
CompletableFuture<String> ft = CompletableFuture.supplyAsync(
() -> "hi", executorService);
Supplier is a
functional
interface
Similar to
Callable
if no executor is provided,
the ForkJoinPool.commonPool will be used
Creating a CompletableFuture
● CompletableFuture<T>
CompletableFuture.supplyAsync(supplier<T>,
executor>
– If no executor is provided, a Common Static pool for all
tasks called ForkJoinPool.commonPool wil be used. This
executor cannot be shutdown
● CompletableFuture<Void>
CompletableFuture.runAsync(runnable, exec)
– Accepts a Runnable instead of a Supplier → no value will
be returned
CompletableFuture
Registering Callbacks
● .thenApply → registers a callback, that will be
executed asynchronously when the future is
ready. It uses the same thread that executed
the future!
● .thenApplyAsynch → same as .thenApply, but
the callback will be executed in a different
thread than the one that completed the future
map in fp terms
CompletableFuture - Nesting and
Composing
CompletableFuture<Order> f1 = persistOrder(o);
CompletableFuture<Order> f2 = f1.thenApply(o → transferOrderToContractor(o));
CompletableFuture<Order> f3 = f2.thenApply(o → updateSearchIndex(o));
CompletableFuture<Order> f4 = f3.thenApply(o → sendMonitoringInfo(o));
//OR, in a line:
CompletableFuture<Order> f1 = persistOrder(o)
.thenApply(o → transferOrderToContractor(o))
.thenApply(o → updateSearchIndex(o))
.thenApply(o → sendMonitoringInfo(o));
thenApply
doesn't block!
operations
are executed
in order, but
do not block
map in fp terms
Set<Order> ordersToProcess = ….;
ordersToProcess.stream().map(o → persistOrder(o)
.thenApply(o → transferOrderToContractor(o))
.thenApply(o → updateSearchIndex(o))
.thenApply(o → sendMonitoringInfo(o)));
CompletableFuture
Multiple Items
CompletableFuture<Order> f1 = persistOrder(o);
CompletableFuture<Order> f2 = f1.thenApply(o → transferOrderToContractor(o));
f2.thenAccept(o → logger.debug(„Order „ + o + „ succesfully processed“);
CompletableFuture
Consuming Final Value
● thenAccept → accepts a function that will be
executed when the CompletableFuture has
finished
CompletableFuture
Error Handling
● exceptionally → accepts a function with the
exception as parameter
● handle → accepts a function with both the
normal result AND the exception as parameter,
but only one of them is set
CompletableFuture<Order> f1 = persistOrderAsynch(o);
f1.exceptionally(e -> sendAlertMessage(e));
//OR
f1.handle((order, ex) -> {
if (ex != null) {
sendAlertMessage(ex);
return null;
} else {
logger.info("Order persisted: " + order);
return order;
}
});
CompletableFuture
Composing
● CompletableFutures provides functions to
combine multiple futures together
● thenCompose → same as thenApply, but the
function that accepts returns a
CompletableFuture
private CompletableFuture<Status> sendData(String data) {…};
CompletableFuture<String> f1 = retrieveData();
CompletableFuture<Status> fs = f1.thenCompose(data → sendData(data));
flatMap in fp terms
CompletableFuture
Combining
● thenCombine → executes a callback when 2
completableFutures finish
CompletableFuture<Address> f1 = retrieveContactAddress(contact);
CompletableFuture<Identification> f2 = retrieveContactIdentification(contact);
CompletableFuture<String> fs = f1.thenCombine(f2,
(address, id) → peristContactData(address id));
CompletableFuture
Accepting one
● acceptEither → returns the future that
completes first
● applyToEither → same than accept either, but
it executes a callback when the first future
completes
CompletableFuture<Contact> f1 = searchContactInDB(name);
CompletableFuture<Contact> f2 = searchContactInIndex(name);
CompletableFuture<Contact> fs = f1.applyToEither(f2,
c → sysout(„Contact found: „ + c);
we do not care who
finishes first.
Just want one
CompletableFuture
Static Methods
● anyOf → static method, similar to acceptEither,
that returns the future that completes first
● allOf → static method, that returns a future that
will complete when all futures complete
CompletableFuture<Contact> f1 = searchContactInDB(name);
CompletableFuture<Contact> f2 = searchContactInIndex(name);
CompletableFuture<Contact> fs = CompletableFuture.anyOf(f1, f2);
we do not care who
finishes first.
Just want one
CompletablFuture - Problems
● Transactions
– In a EE App Server, we can use the
ManagedExecutorService
– Tasks submitted via ManagedExecutorService can
get components @Injected (e.g. EntitiyManager)
@Resource
ManagedExecutorService managedExecutorService;
RX Java
● Java Implementation of ReactiveExtensions (.NET)
● Library for composing asynchronous and event-based
programs
● Introduces the Observable type (extension the Observer GOF
Pattern)
– consumer subscribes to an event, and producer pushes data when
available
● Can be seen as an Iterator that, instead of pulling, gets the data
pushed.
● Futures work on single items – Observables work on multiple
items
event Iterable (pull) Observable (push)
retrieve data T next() onNext(T)
discover error throws Exception onError(Exception)
complete returns onCompleted()
Iterable vs Observable
An Observable is the asynchronous/push "dual" to the
synchronous/pull Iterable
4 3 2 1….
PULL
PUSH
4 3 2 1….
Observable<String> homeMadeSyncObservable = Observable.create(new OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("1");
subscriber.onNext("2");
subscriber.onNext("3");
subscriber.onCompleted();
}
});
Creating Observables - Sync
Observable<String> observable = Observable.from(Arrays.asList("1", "2", "3"));
● Observable.create
• Observable.from
Observable.from(numbers).subscribe(n -> System.out.println("value received: " + n),
t -> System.out.println("Exception thrown: " + t),
() -> System.out.println("observable completed")
);
Subscribing to Observables
● subscribe function accepts three parameters in the form
of functions
– onNext → function to be called when a value is emitted. The
value is passed as parameter to the function.
– onError → function to be called when an exception is emitted.
The exception is passed as parameter to the function
– onComplete → function to be called when the observable
doesn't have any more value to emit (has finished). This function
doesn't accept any parameter.
Holly Lambdas!
Observable.from(numbers).subscribe(new Action1<Integer>() {
@Override
public void call(Integer n) {
System.out.println("value received: " + n);
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable t) {
System.out.println("Exception thrown: " + t);
}
}, new Action0() {
@Override
public void call() {
System.out.println("observable completed");
}
});
Observable.from(numbers).subscribe(n -> System.out.println("value received: " + n),
t -> System.out.println("Exception thrown: " + t),
() -> System.out.println("observable completed")
);Java8
Java7
Subscribing to Observables
● Instead of passing three functions to subscribe,
we can implement the Observer Interface.
public interface Observer<T> {
/**
* Notifies the Observer that the {@link Observable} has finished sending push-based
notifications.
public abstract void onCompleted();
/**
* Notifies the Observer that the {@link Observable} has experienced an error condition.
*/
public abstract void onError(Throwable e);
/**
* Provides the Observer with new data.
*/
public abstract void onNext(T t);
}
Subscribing to Observables
● or, if we are just interested in the values, we
can just „listen“ to the emitted values by
passing just the first function
Observable<Integer> observable = Observable.from(1, 2, 3);
observable.subscribe(t -> System.out.println(t));
4 3 2 1….
OBSERVABLE
OBSERVER
Observable.from(Arrays.asList("1", "2", "3"));
obs.subscribe
(n -> echo("value received: " + n),
t -> echo("Exception thrown: " + t),
() -> echo("observable completed")
);
Subscriptions
● Observable.subscribe() returns a
Subscription object, that offers two methods:
/**
* Stop receiving notifications on the {@link Subscriber}
that was registered when this Subscription was received.
* <p>
* This allows unregistering an {@link Subscriber} before it
has finished receiving all events (ie. before onCompleted is called).
*/
public void unsubscribe();
public boolean isUnsubscribed();
● If we unsubscribe, the Observer will stop
receiving events
Observable<String> homeMadeAsyncObservable = Observable.create(new OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
final Thread thread = new Thread(() -> {
subscriber.onNext("1");
subscriber.onNext("2");
subscriber.onNext("3");
subscriber.onCompleted();
});
thread.start();
}
});
Creating Observables - Async
● Observable.create – Async with Thread
final ExecutorService threadPool = Executors.newCachedThreadPool();
Observable<String> observableWithExecutor = Observable.create(new OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
threadPool.execute(() -> subscriber.onNext("a"));
threadPool.execute(() -> subscriber.onNext("b"));
threadPool.execute(() -> subscriber.onNext("c"));
try {
threadPool.shutdown();
threadPool.awaitTermination(2, TimeUnit.SECONDS);
subscriber.onCompleted();
} catch (InterruptedException e) {
subscriber.onError(e);
}
}
});
Creating Observables - Async
● Observable.create – Async with Executors
Transforming Observables
● map() and flatMap() → same as thenApply and
thenCompose in CompletableFuture
observable.map( n -> n + 1)
→ Observable(2, 3, 4)
observable.flatMap( n -> Observable.from(n+1))
→ Observable(2, 3, 4)
● groupBy, scan, pivot, buffer, window...
Observable<Integer> observable = Observable.from(1, 2, 3);
Filtering Observables
List<String> names = Arrays.asList("Stefan",
"Sebastian", "Ruben", "Robert", "Harald");
Observable.from(names).filter(s ->
s.startsWith("S"));
→ Observable(„Stefan“, „Sebastian“)
Observable.from(names).take(2));
→ Observable(„Stefan“, „Sebastian“)
takeLast, first, elementAt, sample, timeout, distinct, ofType, ...
Combining Observables
zip, join, paralellMerge, combineLatest...
MUCH more on RXJava
https://github.com/Netflix/RxJava/wiki/
Functional Reactive Programming
(Netflix)
● All return types are Observable. The service
layer decides to:
– return immediately with a value (i.e. value in cache)
– or block until result available
– or return immediately and perform execution
asynchronously
Actors
● originated in 1973
● objects that encapsulate state and behaviour
● very lightweight concurrent entities
● process messages asynchronously using an
event-driven receive loop
● they communicate only via messages
● raise the abstraction level to work with events
flowing through the system
Actors
MESSAGE
SENDER
MAILBOX
ACTOR
BEHAVIOUR
DISPATCHER
Actors - Supervising
Actors build „trees
of Actors“, forming
a hierarchical
structure
each actor has exactly one
supervisor, which is the actor that
created it
tasks are split up
and delegated until
they become small
enough to be handled
in one piece
Actors - Supervising
„Parents“ are responsble for
handling „children“'s failures
The recursive structure
then allows to handle
failure at the right
level
different supervision strategies
can be configured: resume,
restart, stop, escalate
Actors
Location Transparent & Distributable
If an actor
communicates
with another one
inside the same
JVM or
remotelly is just
a matter of
configuration program just
holds an Actor's
reference, not
the instance! this
makes possible to
deploy actors
wherever you
want (local,
remote)
all messages
must be
serializable
Actors - Isolation
Actors run completely isolated - the only
way to communicate with them is by
sending messages
Actors – JVM Implementations
http://akka.io/
Akka
● many actors share one thread. one actor typically weights
300 bytes
● an actor only receives one message at a time – while
processing the message, the actor is „thread safe“
(subsequent processing rule)
● router actor: Creates children, and forwards messages to
the children (kind of load balancer)
● distributed by default: everything is dessigned to work
on a distributed environment
● prefer inmutable messages
Akka Persistence
● Command Sourcing: "At least once"
guarantees
– event is persisted before it enters the system (it's
not even validated)
● Event Sourcing: "At most once" guarantees
– event is persisted afterwards (first, the sate of the
actor is changed, and then the event is persisted) -
decouples event changes from side effects
END

More Related Content

PDF
Concurrency Utilities in Java 8
PDF
Java threads
PDF
java-thread
PDF
Java Thread Synchronization
PPTX
Data Types, Variables, and Operators
PDF
Loom Virtual Threads in the JDK 19
PPT
Java multi threading
ODP
Overview of ZeroMQ
Concurrency Utilities in Java 8
Java threads
java-thread
Java Thread Synchronization
Data Types, Variables, and Operators
Loom Virtual Threads in the JDK 19
Java multi threading
Overview of ZeroMQ

What's hot (20)

PPTX
Java Datatypes
PPTX
Java Methods
PDF
Python testing using mock and pytest
PPT
Java Threads and Concurrency
PPT
Java Networking
PDF
Asynchronous JavaScript Programming
PPTX
20.3 Java encapsulation
PPT
Abstract class in java
PDF
Concurrency With Go
PPTX
Database Access With JDBC
PPSX
Strings in Java
PPTX
Introduction to OOP(in java) BY Govind Singh
PPT
Java And Multithreading
PDF
Lambda Expressions in Java
PPT
Introduction to method overloading &amp; method overriding in java hdm
PDF
From Java 11 to 17 and beyond.pdf
PPT
Command Design Pattern
PPT
PDF
Java Collection framework
PPT
standard template library(STL) in C++
Java Datatypes
Java Methods
Python testing using mock and pytest
Java Threads and Concurrency
Java Networking
Asynchronous JavaScript Programming
20.3 Java encapsulation
Abstract class in java
Concurrency With Go
Database Access With JDBC
Strings in Java
Introduction to OOP(in java) BY Govind Singh
Java And Multithreading
Lambda Expressions in Java
Introduction to method overloading &amp; method overriding in java hdm
From Java 11 to 17 and beyond.pdf
Command Design Pattern
Java Collection framework
standard template library(STL) in C++
Ad

Viewers also liked (10)

PPTX
面對移動化App挑戰的架構設計
ODP
Threads and concurrency in Java 1.5
PPTX
Introduction of Android Camera1
PPTX
Java concurrency - Thread pools
PDF
JAVA GUI PART III
PDF
Asynchronous API in Java8, how to use CompletableFuture
PDF
Node.js and Selenium Webdriver, a journey from the Java side
PPTX
C++ ppt
PPTX
Reactive Programming in Java 8 with Rx-Java
PDF
Concurrency: The Good, The Bad and The Ugly
面對移動化App挑戰的架構設計
Threads and concurrency in Java 1.5
Introduction of Android Camera1
Java concurrency - Thread pools
JAVA GUI PART III
Asynchronous API in Java8, how to use CompletableFuture
Node.js and Selenium Webdriver, a journey from the Java side
C++ ppt
Reactive Programming in Java 8 with Rx-Java
Concurrency: The Good, The Bad and The Ugly
Ad

Similar to Concurrent Programming in Java (20)

PPT
Java util concurrent
PPTX
.NET Multithreading/Multitasking
PDF
Effective java item 80 and 81
ODP
Java Concurrency, Memory Model, and Trends
PDF
Tech Talks_04.07.15_Session 3_Martin Toshev_Concurrency Utilities In Java 8
DOCX
Parallel Programming With Dot Net
PPTX
Fork and join framework
ODP
Java Concurrency
PDF
Java concurrency
PPTX
Parallel & Concurrent ...
PPTX
Concurrency with side-effects – cats way
PDF
What is new in java 8 concurrency
PPTX
Async and parallel patterns and application design - TechDays2013 NL
PDF
Programming with Threads in Java
KEY
Modern Java Concurrency
PDF
PDF
Structured concurrency with Kotlin Coroutines
PDF
Concurrency-5.pdf
PDF
Looming Marvelous - Virtual Threads in Java Javaland.pdf
Java util concurrent
.NET Multithreading/Multitasking
Effective java item 80 and 81
Java Concurrency, Memory Model, and Trends
Tech Talks_04.07.15_Session 3_Martin Toshev_Concurrency Utilities In Java 8
Parallel Programming With Dot Net
Fork and join framework
Java Concurrency
Java concurrency
Parallel & Concurrent ...
Concurrency with side-effects – cats way
What is new in java 8 concurrency
Async and parallel patterns and application design - TechDays2013 NL
Programming with Threads in Java
Modern Java Concurrency
Structured concurrency with Kotlin Coroutines
Concurrency-5.pdf
Looming Marvelous - Virtual Threads in Java Javaland.pdf

Recently uploaded (20)

PDF
Unit-1 introduction to cyber security discuss about how to secure a system
PPTX
PPT_M4.3_WORKING WITH SLIDES APPLIED.pptx
PDF
www-codemechsolutions-com-whatwedo-cloud-application-migration-services.pdf
PPTX
nagasai stick diagrams in very large scale integratiom.pptx
PDF
Automated vs Manual WooCommerce to Shopify Migration_ Pros & Cons.pdf
PPTX
ppt for upby gurvinder singh padamload.pptx
PDF
Behind the Smile Unmasking Ken Childs and the Quiet Trail of Deceit Left in H...
PDF
Paper PDF World Game (s) Great Redesign.pdf
PPTX
Slides PPTX World Game (s) Eco Economic Epochs.pptx
PPTX
Internet___Basics___Styled_ presentation
PDF
LABUAN4D EXCLUSIVE SERVER STAR GAMING ASIA NO.1
PDF
Best Practices for Testing and Debugging Shopify Third-Party API Integrations...
PPTX
introduction about ICD -10 & ICD-11 ppt.pptx
PDF
Testing WebRTC applications at scale.pdf
PPTX
ENCOR_Chapter_10 - OSPFv3 Attribution.pptx
DOCX
Unit-3 cyber security network security of internet system
PDF
“Google Algorithm Updates in 2025 Guide”
PPTX
QR Codes Qr codecodecodecodecocodedecodecode
PPTX
Introduction about ICD -10 and ICD11 on 5.8.25.pptx
PDF
Tenda Login Guide: Access Your Router in 5 Easy Steps
Unit-1 introduction to cyber security discuss about how to secure a system
PPT_M4.3_WORKING WITH SLIDES APPLIED.pptx
www-codemechsolutions-com-whatwedo-cloud-application-migration-services.pdf
nagasai stick diagrams in very large scale integratiom.pptx
Automated vs Manual WooCommerce to Shopify Migration_ Pros & Cons.pdf
ppt for upby gurvinder singh padamload.pptx
Behind the Smile Unmasking Ken Childs and the Quiet Trail of Deceit Left in H...
Paper PDF World Game (s) Great Redesign.pdf
Slides PPTX World Game (s) Eco Economic Epochs.pptx
Internet___Basics___Styled_ presentation
LABUAN4D EXCLUSIVE SERVER STAR GAMING ASIA NO.1
Best Practices for Testing and Debugging Shopify Third-Party API Integrations...
introduction about ICD -10 & ICD-11 ppt.pptx
Testing WebRTC applications at scale.pdf
ENCOR_Chapter_10 - OSPFv3 Attribution.pptx
Unit-3 cyber security network security of internet system
“Google Algorithm Updates in 2025 Guide”
QR Codes Qr codecodecodecodecocodedecodecode
Introduction about ICD -10 and ICD11 on 5.8.25.pptx
Tenda Login Guide: Access Your Router in 5 Easy Steps

Concurrent Programming in Java

  • 2. Index ● Concurrency ● Threads ● Executors ● ForkJoin ● Paralell Streams ● CompletableFuture ● RXJava ● Actors
  • 3. Concurrency? „a property of systems in which several computations are executing simultaneously, and potentially interacting with each other“ http://en.wikipedia.org/wiki/Concurrency_(computer_science)
  • 6. Amdahl's Law The speedup of a program using multiple processors in parallel computing is limited by the sequential fraction of the program. For example, if 95% of the program can be parallelized, the theoretical maximum speedup using parallel computing would be 20× as shown in the diagram, no matter how many processors are used.
  • 8. Java1.0 - Threads public class TestRunnable implements Runnable { public void run() { //do something } } Thread t = new Thread(new TestRunnable()); t.start(); //Thread starts t.join(1000); //Waits 1 second until thread finishes t.isAlive(); //checks if thread is alive t.interrupt(); // stops thread
  • 9. Communication betwen Threads ● Threads communicate by sharing access to fields ● This kind of communication can lead to: – Thread interference: sequence of steps overlap, leading to wrong results. – Memory consistency errors: changes to objects are not immediatelly visible to other threads
  • 10. Thread Interference – sequence of steps overlap, leading to wrong results
  • 11. Memory Consistency Errors //thread A increments counter counter++; // counter is shared by 2 threads int counter = 0; Thread A Thread B //thread B prints out counter, // right after A's change System.out.println(counter); Which value prints out B? there's no guarantee that thread A's change to counter will be visible to thread B, unless the programmer has established a happens-before relationship between these two statements
  • 12. Threads ● To prevent Thread Interference and Memory Consistency errors, we use synchronization, that can introduce Thread Contention – Deadlocks: threads wait for each other forever. – Starvation: thread blocks for a long time, because synchronized block takes too much time to execute. – Livelocks: threads introduce logic to avoid deadlocks, but they fail reapeatedly.
  • 14. Thread Problems ● Expensive to create – CPU + RAM (around. 512Kb per Thread!) ● Performance overhead when CPU does context switching (switching between threads) – Everytime a thread blocks or sleeps, context is switched ● Memory is shared around threads – Problem with concurrent access to shared objects ● Difficult to control flow ● Difficult to control the number of threads started ● Locks to control access to shared resources – Can introduce thread contention
  • 15. Java5 – Concurrency Enhancements ● Atomic Numbers (AtomicInteger): get and increment a value atomically ● Concurrent Collections (e.g. ConcurrentHashMap): supports concurrent reads and updates ● ExecutorService ● Futures
  • 16. ExecutorService ● Takes care of executing (and controlling the execution) of asynchronous tasks ● Configurable Thread Pools – CorePoolSize – MaximumPoolSize, – KeepAliveTime – ThreadFactory – RejectedExecutionHandler ● Predefined Executors – Cached – Fixed – Scheduled – SingleThreaded http://blog.jessitron.com/2014/01/choosing-executorservice.html
  • 17. Executor Executor executor = new ThreadPoolExecutor(...) executor.execute(new Runnable() { public void run() { //execute task } }); ● Parent Interface of ExecutorService ● Just provides one method: execute
  • 18. ExecutorService //creates the executor service ExecutorService executorService = Executors.newFixedThreadPool(5); //submits a task to be executed asynchronously Future<String> future = executorService.submit(new Callable<String>() { @Override public String call() throws Exception { return "hi"; } }); //blocks until the result is ready String message = future.get(); // no more executions will be accepted executorService.shutdown(); // blocks until all tasks have completed execution executorService.awaitTermination(1, TimeUnit.SECONDS);
  • 19. ExecutorService + Callable + Future //submits a task to be executed asynchronously Future<String> future = executorService.submit(new Callable<String>() { @Override public String call() throws Exception { return "hi"; } }); //blocks until the result is ready String message = future.get(); Blocks until result is ready (thread has finished) ● Callable allows threads to return a result ● Future holds the result of the asynchronous computation
  • 20. Future methods ● get() – BLOCKS until result is ready ● get(timeout) throws TimeoutException ● cancel(mayInterruptIfRunning) – If task has not started, it will not be started – Otherwise, if mayInterruptIfRunning is true, it will Interrupt ● isDone() ● isCancelled()
  • 21. ExecutorService – more methods ● List<Future> invokeAll(Collection <Callable> Tasks – Executes all tasks, and returns when ALL have completed execution ● Object invokeAny(Collection<Callable>) – Starts execution of all tasks and returns the result of one finished task. Tasks that have not completed, are cancelled. ● invoke* and await* methods support timeout parameters. If task doesn't finish on time, method still returns
  • 22. ExecutorService - Pros ● Now we can: – Cache Threads => less overhead – Control Size of Pool => less risk of OOM – Easily retrieve values of asynchronous computation (Future) – Submit multiple tasks simultaneously
  • 23. Executors - Cons ● How to control multiple executions? Future<String> fA = executorService.submit(....); Future<String> fB = executorService.submit(....); Future<String> fC = executorService.submit(....); String a = fA.get(); String b = fB.get(); String c = fC.get(); What if fB and fC are ready before fA?
  • 24. Executors - Cons ● How to nest calls? Future<String> fA = executorService.submit(new RemoteCall()); Future<String> fB = executorService.submit(new RemoveCallWithParam(fA.get()); ….......... String a = fA.get(); String a = fB.get(); fA.get() BLOCKS!
  • 25. Callbacks executorService.execute(new RemoteCall(new Callback() { public void notify(Object param) { //remote call has finished – do something } })); //continue doing something interface Callback { void notify(Object param); } class RemoteCall implements Runnable { private Callback callback; public RemoteCall(Callback callback) { this.callback = callback; } public void run() { //execute remote call callback.notify(param) } } when RemoteCall finishes it notifies the registered callback no blocking
  • 26. Executors - Cons ● Futures block and are difficult to nest ● Callbacks do not block, but do not solve the problem of nested composition
  • 27. Java7 - ForkJoin ● Implementation of ExecutorService ● Aims to utilize a multi-core architecture at a maximum ● Uses a work-stealing algorithm: if a worker runs out of tasks, can steal work from others ● Useful for recursive tasks if (my portion of the work is small enough) do the work directly else split my work into two pieces invoke the two pieces and wait for the results
  • 29. public class ForkSum extends RecursiveAction { private final int[] array; private final int start; private final int end; private final AtomicInteger result; public ForkSum(int[] array, int start, int end, AtomicInteger result) { super(); this.array = array; this.start = start; this.end = end; this.result = result; } private void computeDirectly() { int partialSum = 0; for (int i = start; i < end; i++) { partialSum += array[i]; } result.addAndGet(partialSum); } @Override protected void compute() { if ((start - end) < 10) { computeDirectly(); } else { int delta = (end - start) / 2; ForkSum a = new ForkSum(array, start, start + delta, result); ForkSum b = new ForkSum(array, start + delta + 1, end, result); invokeAll(a, b); } }
  • 30. int[] array = new int[2046]; Arrays.fill(array, 2); AtomicInteger result = new AtomicInteger(0); ForkSum forkSum = new ForkSum(array, 0, array.length, result); ForkJoinPool pool = new ForkJoinPool(); pool.invoke(forkSum); System.out.println(forkSum.getResult()); ForkJoinPool uses work stealing We can set the „parallelism level“ to ForkJoinPool (defaults to number of processors)
  • 31. Java7 - ForkJoin ● Only really useful for recursive tasks ● Does not help with the problems with had in the Executors (blocking & nested composition)
  • 32. Java8 – Streams // PROBLEM: Perform a time-intensive computation // to each element of the list List<Integer> col = Arrays.asList(1, 2, 3); // Procedural Solution List<Integer> colResult = new ArrayList<Integer>(); for (Integer i : col) { colResult.add(expensiveOperation(i)); } //Functional Solution: use map() with a HighOrderFunction List<Integer> colResultF = col.stream().map(i -> expensiveOperation(i)) .collect(Collectors.toList());
  • 33. Java8 – Parallel Streams //Functional Solution+: // parallelize the stream // and use map() with a HighOrderFunction List<Integer> colResultFP = col.parallelStream().map(i -> expensiveOperation(i)) .collect(Collectors.toList());
  • 34. Java8 - CompletableFuture ● Futures with – Callbacks – Transformations – Possibility to explicitly set a value in the Future (i.e. Promise)
  • 35. Completing a CompletableFuture //CALLEE public CompletableFuture<String> doSomething() { final CompletableFuture<String> future = createFuture(); // do something (synch or asynch) // when ready, call future.complete("hi"); // that will unlock the clients waiting for the future return future; } //CALLER CompletableFuture<String> cf = doSomething(); // Blocks until callee „completes“ the future with f.complete String result = cf.get(); will normally be executed asynch blocks
  • 36. How to get a value from a CompletableFuture ● get() – BLOCKS until the value is present, and returns it ● get(timeout, timeoutUnit) – BLOCKS until the value is present, or the timeout has been reached. If the later , a TimeoutException is thrown ● getNow(valueIfAbsent) – Doesn't block! if the value is present, it returns it; otherwise, the valueIfAbsent param (default) is returned
  • 37. How to complete a CompletableFuture ● complete(value) – completes ok with the value – only the first call takes effect – subsequent calls are ignored ● completeExceptionally(ex) – completes with exception – get() will throw an exception in the caller ● cancel() – completes with a CancellationException
  • 38. Completing a CompletableFuture ● Why is this useful? – We can execute a task sometimes in synchronous, and sometimes in asynchronous mode, without having to change the client. We just deliver a CompletableFuture, and the implementation decides the execution mode.
  • 39. Creating a CompletableFuture // <Java7 CompletableFuture<String> f = CompletableFuture.supplyAsync( new Supplier<String>() { @Override public String get() { // perform task return "hi"; } }, executorService); // OR Using Lambdas CompletableFuture<String> ft = CompletableFuture.supplyAsync( () -> "hi", executorService); Supplier is a functional interface Similar to Callable if no executor is provided, the ForkJoinPool.commonPool will be used
  • 40. Creating a CompletableFuture ● CompletableFuture<T> CompletableFuture.supplyAsync(supplier<T>, executor> – If no executor is provided, a Common Static pool for all tasks called ForkJoinPool.commonPool wil be used. This executor cannot be shutdown ● CompletableFuture<Void> CompletableFuture.runAsync(runnable, exec) – Accepts a Runnable instead of a Supplier → no value will be returned
  • 41. CompletableFuture Registering Callbacks ● .thenApply → registers a callback, that will be executed asynchronously when the future is ready. It uses the same thread that executed the future! ● .thenApplyAsynch → same as .thenApply, but the callback will be executed in a different thread than the one that completed the future map in fp terms
  • 42. CompletableFuture - Nesting and Composing CompletableFuture<Order> f1 = persistOrder(o); CompletableFuture<Order> f2 = f1.thenApply(o → transferOrderToContractor(o)); CompletableFuture<Order> f3 = f2.thenApply(o → updateSearchIndex(o)); CompletableFuture<Order> f4 = f3.thenApply(o → sendMonitoringInfo(o)); //OR, in a line: CompletableFuture<Order> f1 = persistOrder(o) .thenApply(o → transferOrderToContractor(o)) .thenApply(o → updateSearchIndex(o)) .thenApply(o → sendMonitoringInfo(o)); thenApply doesn't block! operations are executed in order, but do not block map in fp terms
  • 43. Set<Order> ordersToProcess = ….; ordersToProcess.stream().map(o → persistOrder(o) .thenApply(o → transferOrderToContractor(o)) .thenApply(o → updateSearchIndex(o)) .thenApply(o → sendMonitoringInfo(o))); CompletableFuture Multiple Items
  • 44. CompletableFuture<Order> f1 = persistOrder(o); CompletableFuture<Order> f2 = f1.thenApply(o → transferOrderToContractor(o)); f2.thenAccept(o → logger.debug(„Order „ + o + „ succesfully processed“); CompletableFuture Consuming Final Value ● thenAccept → accepts a function that will be executed when the CompletableFuture has finished
  • 45. CompletableFuture Error Handling ● exceptionally → accepts a function with the exception as parameter ● handle → accepts a function with both the normal result AND the exception as parameter, but only one of them is set CompletableFuture<Order> f1 = persistOrderAsynch(o); f1.exceptionally(e -> sendAlertMessage(e)); //OR f1.handle((order, ex) -> { if (ex != null) { sendAlertMessage(ex); return null; } else { logger.info("Order persisted: " + order); return order; } });
  • 46. CompletableFuture Composing ● CompletableFutures provides functions to combine multiple futures together ● thenCompose → same as thenApply, but the function that accepts returns a CompletableFuture private CompletableFuture<Status> sendData(String data) {…}; CompletableFuture<String> f1 = retrieveData(); CompletableFuture<Status> fs = f1.thenCompose(data → sendData(data)); flatMap in fp terms
  • 47. CompletableFuture Combining ● thenCombine → executes a callback when 2 completableFutures finish CompletableFuture<Address> f1 = retrieveContactAddress(contact); CompletableFuture<Identification> f2 = retrieveContactIdentification(contact); CompletableFuture<String> fs = f1.thenCombine(f2, (address, id) → peristContactData(address id));
  • 48. CompletableFuture Accepting one ● acceptEither → returns the future that completes first ● applyToEither → same than accept either, but it executes a callback when the first future completes CompletableFuture<Contact> f1 = searchContactInDB(name); CompletableFuture<Contact> f2 = searchContactInIndex(name); CompletableFuture<Contact> fs = f1.applyToEither(f2, c → sysout(„Contact found: „ + c); we do not care who finishes first. Just want one
  • 49. CompletableFuture Static Methods ● anyOf → static method, similar to acceptEither, that returns the future that completes first ● allOf → static method, that returns a future that will complete when all futures complete CompletableFuture<Contact> f1 = searchContactInDB(name); CompletableFuture<Contact> f2 = searchContactInIndex(name); CompletableFuture<Contact> fs = CompletableFuture.anyOf(f1, f2); we do not care who finishes first. Just want one
  • 50. CompletablFuture - Problems ● Transactions – In a EE App Server, we can use the ManagedExecutorService – Tasks submitted via ManagedExecutorService can get components @Injected (e.g. EntitiyManager) @Resource ManagedExecutorService managedExecutorService;
  • 51. RX Java ● Java Implementation of ReactiveExtensions (.NET) ● Library for composing asynchronous and event-based programs ● Introduces the Observable type (extension the Observer GOF Pattern) – consumer subscribes to an event, and producer pushes data when available ● Can be seen as an Iterator that, instead of pulling, gets the data pushed. ● Futures work on single items – Observables work on multiple items
  • 52. event Iterable (pull) Observable (push) retrieve data T next() onNext(T) discover error throws Exception onError(Exception) complete returns onCompleted() Iterable vs Observable An Observable is the asynchronous/push "dual" to the synchronous/pull Iterable
  • 53. 4 3 2 1…. PULL PUSH 4 3 2 1….
  • 54. Observable<String> homeMadeSyncObservable = Observable.create(new OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { subscriber.onNext("1"); subscriber.onNext("2"); subscriber.onNext("3"); subscriber.onCompleted(); } }); Creating Observables - Sync Observable<String> observable = Observable.from(Arrays.asList("1", "2", "3")); ● Observable.create • Observable.from
  • 55. Observable.from(numbers).subscribe(n -> System.out.println("value received: " + n), t -> System.out.println("Exception thrown: " + t), () -> System.out.println("observable completed") ); Subscribing to Observables ● subscribe function accepts three parameters in the form of functions – onNext → function to be called when a value is emitted. The value is passed as parameter to the function. – onError → function to be called when an exception is emitted. The exception is passed as parameter to the function – onComplete → function to be called when the observable doesn't have any more value to emit (has finished). This function doesn't accept any parameter.
  • 56. Holly Lambdas! Observable.from(numbers).subscribe(new Action1<Integer>() { @Override public void call(Integer n) { System.out.println("value received: " + n); } }, new Action1<Throwable>() { @Override public void call(Throwable t) { System.out.println("Exception thrown: " + t); } }, new Action0() { @Override public void call() { System.out.println("observable completed"); } }); Observable.from(numbers).subscribe(n -> System.out.println("value received: " + n), t -> System.out.println("Exception thrown: " + t), () -> System.out.println("observable completed") );Java8 Java7
  • 57. Subscribing to Observables ● Instead of passing three functions to subscribe, we can implement the Observer Interface. public interface Observer<T> { /** * Notifies the Observer that the {@link Observable} has finished sending push-based notifications. public abstract void onCompleted(); /** * Notifies the Observer that the {@link Observable} has experienced an error condition. */ public abstract void onError(Throwable e); /** * Provides the Observer with new data. */ public abstract void onNext(T t); }
  • 58. Subscribing to Observables ● or, if we are just interested in the values, we can just „listen“ to the emitted values by passing just the first function Observable<Integer> observable = Observable.from(1, 2, 3); observable.subscribe(t -> System.out.println(t));
  • 59. 4 3 2 1…. OBSERVABLE OBSERVER Observable.from(Arrays.asList("1", "2", "3")); obs.subscribe (n -> echo("value received: " + n), t -> echo("Exception thrown: " + t), () -> echo("observable completed") );
  • 60. Subscriptions ● Observable.subscribe() returns a Subscription object, that offers two methods: /** * Stop receiving notifications on the {@link Subscriber} that was registered when this Subscription was received. * <p> * This allows unregistering an {@link Subscriber} before it has finished receiving all events (ie. before onCompleted is called). */ public void unsubscribe(); public boolean isUnsubscribed(); ● If we unsubscribe, the Observer will stop receiving events
  • 61. Observable<String> homeMadeAsyncObservable = Observable.create(new OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { final Thread thread = new Thread(() -> { subscriber.onNext("1"); subscriber.onNext("2"); subscriber.onNext("3"); subscriber.onCompleted(); }); thread.start(); } }); Creating Observables - Async ● Observable.create – Async with Thread
  • 62. final ExecutorService threadPool = Executors.newCachedThreadPool(); Observable<String> observableWithExecutor = Observable.create(new OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { threadPool.execute(() -> subscriber.onNext("a")); threadPool.execute(() -> subscriber.onNext("b")); threadPool.execute(() -> subscriber.onNext("c")); try { threadPool.shutdown(); threadPool.awaitTermination(2, TimeUnit.SECONDS); subscriber.onCompleted(); } catch (InterruptedException e) { subscriber.onError(e); } } }); Creating Observables - Async ● Observable.create – Async with Executors
  • 63. Transforming Observables ● map() and flatMap() → same as thenApply and thenCompose in CompletableFuture observable.map( n -> n + 1) → Observable(2, 3, 4) observable.flatMap( n -> Observable.from(n+1)) → Observable(2, 3, 4) ● groupBy, scan, pivot, buffer, window... Observable<Integer> observable = Observable.from(1, 2, 3);
  • 64. Filtering Observables List<String> names = Arrays.asList("Stefan", "Sebastian", "Ruben", "Robert", "Harald"); Observable.from(names).filter(s -> s.startsWith("S")); → Observable(„Stefan“, „Sebastian“) Observable.from(names).take(2)); → Observable(„Stefan“, „Sebastian“) takeLast, first, elementAt, sample, timeout, distinct, ofType, ...
  • 65. Combining Observables zip, join, paralellMerge, combineLatest...
  • 66. MUCH more on RXJava https://github.com/Netflix/RxJava/wiki/
  • 67. Functional Reactive Programming (Netflix) ● All return types are Observable. The service layer decides to: – return immediately with a value (i.e. value in cache) – or block until result available – or return immediately and perform execution asynchronously
  • 68. Actors ● originated in 1973 ● objects that encapsulate state and behaviour ● very lightweight concurrent entities ● process messages asynchronously using an event-driven receive loop ● they communicate only via messages ● raise the abstraction level to work with events flowing through the system
  • 70. Actors - Supervising Actors build „trees of Actors“, forming a hierarchical structure each actor has exactly one supervisor, which is the actor that created it tasks are split up and delegated until they become small enough to be handled in one piece
  • 71. Actors - Supervising „Parents“ are responsble for handling „children“'s failures The recursive structure then allows to handle failure at the right level different supervision strategies can be configured: resume, restart, stop, escalate
  • 72. Actors Location Transparent & Distributable If an actor communicates with another one inside the same JVM or remotelly is just a matter of configuration program just holds an Actor's reference, not the instance! this makes possible to deploy actors wherever you want (local, remote) all messages must be serializable
  • 73. Actors - Isolation Actors run completely isolated - the only way to communicate with them is by sending messages
  • 74. Actors – JVM Implementations http://akka.io/
  • 75. Akka ● many actors share one thread. one actor typically weights 300 bytes ● an actor only receives one message at a time – while processing the message, the actor is „thread safe“ (subsequent processing rule) ● router actor: Creates children, and forwards messages to the children (kind of load balancer) ● distributed by default: everything is dessigned to work on a distributed environment ● prefer inmutable messages
  • 76. Akka Persistence ● Command Sourcing: "At least once" guarantees – event is persisted before it enters the system (it's not even validated) ● Event Sourcing: "At most once" guarantees – event is persisted afterwards (first, the sate of the actor is changed, and then the event is persisted) - decouples event changes from side effects
  • 77. END

Editor's Notes

  • #7: The speedup of a program using multiple processors in parallel computing is limited by the sequential fraction of the program. For example, if 95% of the program can be parallelized, the theoretical maximum speedup using parallel computing would be 20× as shown in the diagram, no matter how many processors are used.