Java Pro Flashcards
Thread, process
Thread - smallest unit of execution that can be scheduled by the OS on CPU core
Process - grouping of associated threads executing in shared environment - memory space and can communicate directly with one another
System thread vs user-defined thread in JVM
system thread
- created by JVM
- runs in BG
- GC thread
user-defined thread
- created by app dev to accomplish a specific task
All jvm apps are multi-thread but may be single-user-defined-threaded (the main one calling… main())
Daemon thread
Thread that will not prevent JVM from exiting after program fiinishes
Java app terminates when the only threads running are daemon
GC thread is daemon thread
User-defined threads can also be marked as daemon
Thread scheduler
Determines which thread should be executing
Might be round-robin schedule - all threads receive equal number of CPU cycles, threads revisited in circular order
When thread allotted time is complete but it didn’t finish yet - context switch
threads can have priorities - higher priority thread will interrupt the lower-priority one if its executing
Context switch
Process of storing thread’s current state and later restoing the state of the one to continue exec which cost a bit CPU time
Runnable
functional interface, takes no args, returns nothing
Commonly used to define the work for separate thread
when java Thread is run?
After start method is called it can be scheduled by OS for execution but exact time is unknown
To extend thread or implement Runnable
- if multiple tasks would share rules like priority extended thread could be useful
- Extending thread locks you to base concrete class
- Implementing runnable allows for better separation-of-concerns from object performing the task
- Runnable can be used in Concurrency APIs
ExecutorService bitch - fuck explicit threads
While while loop polling is bad practice
Spinning while loop without delay like sleep eats a lot of CPU resources for no reason
Thread executor
They create non daemon threads when first task is submitted so shutdown should be called
Shutdown prevents new tasks from being submitted
Previously submitted tasks will continue
New thread executor
Active -> Shutting down -> Shutdown
shutdownNow() would attempt to stop running tasks, discards ones not started yet; returns list of not started tasks
Threads that never terminate cannot be interrupted though
Do not implements AutoClosable - must use finally
Task submission
- execute - async fire-and-forget, no way to get result
- submit - returns Future to determine state of task
Callable
Checked Exception
call method
Can return value
Runnable equivalent for concurrency APIs
Thread Pools
Group of pre-instantiated, reusable threads available to perform a set of arbitrary tasks
- newSingleThreadExecutor - single worker thread operating off an unbounded queue, results processed sequentially in order of submission
- newSingleThreadScheduledExecutor - can schedule commands to run after delay or periodically
- newCachedThreadPool - creates new threads as needed, will reuse previously constructed ones when they’re available; unbounded thread pool size; good for many short-live async tasks; long lived processes - nope
- newFixedThreadPool - reuses fixed num of threads, operates off a shared unbounded queue
- newScheduledThreadPool - pool that can schedule
IO tasks that depend on external resources (file system, network, db) are good for large thread pool as tasks are not CPU bound and there’s a lot of waiting
java.util.concurrent.atomic
Package hlping coordinate access to primitive values and object references
AtomicBoolean, AtomicInteger, AtomicIntegerArray, AtomicLong, AtomicLongArray, AtomicReference, AtomicReferenceArray
get, set, getAndSet, incrementAndGet…
Sycnhronized block
monitor = lock - mutual exclusion - at most one thread executes marked segment of code at given time
synchronized keyword
Any object can be monitor but must be the same instance to work
Static synchronization
Can be done using class object (Class.class) Works for all instances
Concurrent collections
Convenient classes, prevent mistakes in custom implementations like forgetting synchronizing some method
Solve Memory consistency errors - two threads have inconsistent views of the same data (writes on one thread not seen by other)
When 2 threads modify non-concurrent collection JVM may throw ConcurrentModificationException at runtime (can happen also when modifying collection while iterating it)
blockingdequeue/queue - offer, offerFirst, offerLast - with timeouts and throws interrupted exc
Collections.synchronizedXyz to get concurrent safe reference for existing non-concurrent collection
Sync is on get/set but not for iterators so needs to use synchronized block
CopyOnWrite collections
When element is added new underlying collection is made and old elements + new one is copied over. Old iterators still work using previous version of collection.
Good when reads are more common than writes
Parallel Streams APIs
collection.stream().parallel()
Arrays.asList().parallelStream() from collection interface
Some operations do not preserve parallelity (isParallel() to test - for example flatMap or concat if neither of 2 streams are parallel)
forEachOrdered - forces parallel stream to process elements in order
Performance gain from property of many stream ops - operations can be executed independently
There is a cost to setup parallel stream structures and threads so not guaranteed to speed anything up
TIP: don’t use lambdas with side effect within streams
TIP: use sync collections with parallel streams or weird side effects happen (like null values when 2 threads trigger list resize)
Ordered and unordered streams
By default all are ordered using unordered() we can tell JVM if order can be ignored (no "unordering" operations are triggered, it's just a cue)
Stream reduce
Identity, accumulator, combiner
Combines stream into single object
Identity must be defined that for all elements in stream identity applied to an element gives that element
Accumulator must be associative and stateless:
(a op b) op c = a op (b op c)
Combiner must also be assoc and stateless and must be compatible with identity:
combiner.apply(el, accumulator.apply(identity, t)) = accumulator.apply(u,t)
Important properties when working on unordered parallel streams
Explicit combiner method allows JVM to better partition operations in stream
CyclicBarrier
await() method
waits for “limit” threads to await until it releases them
Be aware of deadlocks if barrier is used in thread pool of less than limit threads
ForkJoinPool
pool.invoke()
Recursive action - void compute
Recursive task - T compute
recursive task uses fork on other tasks and then joins
fork join task can invoke new fork join tasks/actions
Idea is each invocation divides subtasks into smaller one until there’s no point splitting
FJP will determine based on available processor count how many threads to make
Liveness issues
Liveness - ability of an app to execute in a timely manner
If there’s an issue app is unresponsive/hanged
3 common types of issues:
- deadlock
- starvation
- livelock
Deadlock:
2 or more threads are blocked forever as each is waiting for the other
Foxy and Tails - one eats first and then drinks, other drink first then eats; neither shares and they finish their meals only if they have both exclusive access to food and water
One gets to the food, other to the water - they wait forevah
Prevention - all threads request resources in the same order
Starvation:
Single thread is perpetually denied access to a shared resource/lock. Thread is alive but can’t finish its work as other evict it
Livelock:
Two+ threads are blocked forever - special case of stravation
Threads try to acquire a set of locks, fail and restart the process
Foxy and Tails after acquiring food or water let it go and goes for the opposite… forever
Race conditions
Creating account with the same name by 2 diff user at the same time
- both created - integrity issue
- none created - users retry, unlikely the hit race condition again
- only one created - ideal
Type Erasure
Specifying a generic type allows enforcing proper use at compile time only!
Behind the scene generic classes have generic T replaced with Object
There is only 1 class, no different classes per parametrized type
It’s required for backwards compatibility with older Java
Compiler automatically adds relevant casts
Raw type of generic
Interface implemented without specifying some generic type - it’s assumed to be Object
Generics limitations
- can’t call ctor new T() (would be object at runtime)
- create an array of that static type (array of objects)
- call instanceof - at runtime every T is just Object
- user primitive types as generic type param (must use wrapper classes)
- create a static variable as a generic type parameter (type is linked to the instance of the class)
Generic methods
public static T identity(T p) {return p}
Invoking explicitly
Class.identity(p)
Bounds
Restrict what type can be used in that wildcard position
Bounded parameter type - specifies bound for the generic
Wildcard generict type - unknown generic type represented by “?”
Upper bound - ? extends type
Lower bound - ? super type
Cannot be used as return value of a method etc
Arrays vs ArrayList - storing wrong type
Object[] x = new String[]; // legal for compiler but... ...ArrayStoreException runtime exception will be thrown if object of invalid type is inserted though List l = new ArrayList() // illegal for compiler
Ubounded/Upper bounded generics caveats
List extends Parentclass> becomes immutable as java doesn't know which concrete class is there (Subclass or parentclass?) Lower bounds are fine
What to use if we need a Stack
ArrayDeque as Stack is oooold
LinkedList
Implements List and Queue interfaces
Constant time taking top and bottom elements
Linear access to other indices
Set implementations
HashSet - hash table of elements, hashCode of objects used; checking if element exists is O(1)
TreeSet - stores its elements in a sorted tree structure; checking element presence and updating is O(logN)
NavigableSet interface
Methods: lower(E e), floor(E e), ceiling, higher
Return closests element of collection where element is lt/lte/gt/gte than provided arg
Map implementations
HashMap - hash table, linear insert, no insertion order
LinkedHashMap - preserves insertion order
TreeMap - sorted tree structure; logN for adding/checking
Hashtable is passe
Which datastructures disallow null values to be inserted?
Those preserving order (TreeSet, TreeMap)
ArrayDeque also - poll method uses null as special ret value
Hashtable - no null keys or values but it’s passe so fuckit
Functional interface
One that has single abstract method and can be converted to lambda
Comparable vs Comparator
compareTo vs compare
Comparator doesn’t require compared classes to implement any interface while Comparable requires argument of compareTo to be comparable
1 vs 2 parameters
second is lambda usually
Comparators let separate sort order from the object to be sorted
Method reference
Class:methodName
Shorter than specifying lambda
Returns a functional interface