Skip to content

Instantly share code, notes, and snippets.

@shyan1
Last active February 16, 2023 03:33
Show Gist options
  • Save shyan1/34f86ec49a01bd6b4630f9d2e4926126 to your computer and use it in GitHub Desktop.
Save shyan1/34f86ec49a01bd6b4630f9d2e4926126 to your computer and use it in GitHub Desktop.
Composable Futures with Akka 2.0
Youtube link: youtube.com/watch?v=VCattsfHR4o
Threads
- Independent, heap-sharing execution contexts
- Scheduled by the Operating System
- Creation is expensive in Java
- Pools create additional complexity
- Cache coherency issues
Standard Thread Pools
- Cached
- Fixed
- Scheduled
- Single
- Single scheduled
- Fork/join (JDK7 and improved jsr166y)
- Variants with/without daemon threads often required
Concurrency Definitions
- Concurrent tasks are stateful, often with complex interactions
- Parallelizable tasks are stateless, do not interact, and are composable
java.util.concurrent
- Akka is built on top of java.util.concurrent(j.u.c)
- Futures are designed to be used with a `Callable`, which returns a result
- `Executors` contain factories and utility methods for concurrent classes
- `ExecutorService.shutdown()`
j.u.c Primitives
- Callable, Runnable
- Threads, thread pools and Executors
- CompletionService, CountDownLatch, concurrent collections, CyclicBarrier,
Phaser, Semaphone, TimeUnit
- Primitive `Future<T>`
j.u.c Is Too Hard To Use
- Multithreaded programs tend to be buggy
- Non-determinism caused by concurrent threads accessing (shared) mutable state
- Actors and transactions manage state and are therefore not the first solution you should consider.
- To get deterministic processing, avoid (shared) mutable state.
Concurrency Hazards
- CPU registers
- L1, L2 and L3 caches
- L1 cache for each core
- L2 cache shared by pairs of cores
- L3 cache shared by all cores
- Processors are different, so a program may run fine on one system but fail on another
MESI Protocol
- Each processor cache can be in one of four states
- Modified
- Exclusive
- Shared
- Invalid
- When one core writes to main memory, the entire cache block is marked invalid
- Block sizes depend on processor (64 bytes, 128 bytes, etc.)
Large, Realtime Guidelines by Prismatic
- Use functional programming to build fine-grained, flexible abstractions.
- Compose these abstractions to express problem-specific logic.
- Prefer lightweight, composable custom abstractions rather than monolithic frameworks (e.g., Hadoop).
Better Concurrency Options
- Ordered by increasing complexity & overhead
- j.u.c
- Scala parallel collections
- Akka futures (Java & Scala)
- Akka/Scala dataflow
- Akka actors (Java & Scala)
- You can mix & match the above
Scala Parallel Collections
- Very easy to use
- Not configurable
- Block
- Composable
- Easy to reason with
- Benefits from ongoing improvements to ForkJoinPool
Akka/Scala Dataflow
- Callable from Scala only
- Has peculiar operators
- Easy to reason with
- Designed for shared mutable state
- Dataflow blocks are composable
- Good for coordination of asynchrnous activities
- Good for consolidating multiple sources of data
Akka Actors
- Callable from Java & Scala
- Over-hyped
- Most complex option
- Distributed concurrency: can scale beyond one motherboard
- Not composable
- Can be difficult or impossible to prove correct
- THis should be your last option to consider
Akka Futures
- Callable from Java & Scala
- More flexible than Scala parallel collections
- Much less complex than Akka actors
- Composable
- Easy to reason with
- Payloads (Callables) should not have side effects
- Should not be used with shared mutable state
What is a Future ?
- Holder for a result that will become available at later time
- Each future is backed by a thread
- If the computation fails, the future can also hold the resulting `Throwable`.
- Write-once (immutable)
- Akka and Twitter futures are composable and transformable (j.u.c futures are not)
Akka & Twitter Futures
- Manage concurrency
- Higher-level than j.u.c. primitives
- Immutable
- Inexpensive
- Can be preset to a value or exception when created
- Blocking and non-blocking operations supported
Composable Futures
- Operations on a future or a collection of futures can be chained together without blocking
- Transformations such as `map` and `flatMap` can be applied to a single future
- Collections of futures can be manipulated
Akka Future Operations
- flatMap, map
- flow
- foreach, zip, firstCompletedOf, fold, reduce, sequence, traverse
- andThen, fallbackTo, onComplete, onFailure, onSuccess, recover
Composable Futures Rock
- Twitter uses composable (Twitter) futures, no actors
- KloutAPI uses Play Framework `AsyncResults`, fed by Akka futures, Load dropped in half
Configure Thread Pools at Deployment
- Number and type of processors and other hardware affects behavior
- Interaction with other thread pools
- Akka supports configuration files and configuration strings for setting up thread pools
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment