Java Concurrency - Part 2: High Level Concurrency Objects
3 min readFeb 11, 2021
This article is a part of the Java Programming Language article series.
High Level Concurrency Objects
- Lock Objects
- Executors
- Concurrent Collections
- Atomic Variables
- Concurrent Random Numbers
Lock Objects
- The java.util.concurrent.locks package
- The Lock interface
- The biggest advantage of Lock objects over implicit locks is their ability to back out of an attempt to acquire a lock
- The tryLock method backs out if the lock is not available immediately or before a timeout expires if specified
- The lockInterruptibly method backs out if another thread sends an interrupt before the lock is acquired
Executors
- A high-level API for launching and managing threads
- The java.util.concurrent packages
- Executor Interfaces
- Thread Pools
- Fork/Join
Executor Interfaces
- Executor: a simple interface to launch new tasks
- ExecutorService: a subinterface of Executor with new features to manage the lifecycle of tasks and executor
- ScheduledExecutorService: a subinterface of ExecutorService that supports future and periodic execution of tasks
The Executor Interface
- The execute method
- Accepts a Runnable object
The ExecutorService Interface
- The submit method
- Accepts a Runnable and Callable objects
- Callable object allows the task to return a value
- Returns a Future object to retrieve the Callable return value and to manage the status of the task
The ScheduledExecutorService Interface
- The schedule method
- Executes a Runnable or Callable task after a specified delay
- The scheduleAtFixedRate and scheduleWithFixedDelay methods execute specified tasks repeatedly at defined intervals
Thread Pools
- Consist of worker threads
- Used by most of the executor implementations
- Exists separately from the Runnable and Callable tasks
- Minimizes the memory management overhead due to thread creation
The fixed thread pool
- Has a specified number of threads running
- If a thread is terminated while it is still in use, it is automatically replaced with a new thread
- Tasks are submitted to the pool via an internal queue, which holds extra tasks whenever there are more active tasks than threads
- The newFixedThreadPool factory method in Executors class
Executors class methods
- The newCachedThreadPool method creates an executor with an expandable thread pool, suitable for applications that launch many short-lived tasks
- The newSingleThreadExecutor method creates an executor that executes a single task at a time
- The ScheduledExecutorService versions of these methods
For additional options, construct instances of java.util.concurrent.ThreadPoolExecutor or java.util.concurrent.ScheduledThreadPoolExecutor
Fork/Join
- The fork/join framework is an implementation of the ExecutorService interface
- To use all the available processing power to enhance the performance of your application
- Distributes tasks to worker threads in a thread pool, as with any ExecutorService implementation
- The center of the fork/join framework is the ForkJoinPool class, an extension of the AbstractExecutorService class
- ForkJoinPool implements the core work-stealing algorithm and can execute ForkJoinTask processes
- Work-stealing algorithm: worker threads that run out of things to do can steal tasks from other threads that are still busy
Pseudocode for Basic Use
- Write code that performs a segment of the work
- Wrap this code in a ForkJoinTask subclass, RecursiveTask (which can return a result) or RecursiveAction
- Call the invoke method of a ForkJoinPool instance with the task objects
Blurring an Image
Run
Standard Implementations
- The features that are implemented using the fork/join framework
- The parallelSort method in the java.util.Arrays class
- The methods in the java.util.streams package
Concurrent Collections
- The java.util.concurrent package
- Defines a happens-before relationship between an operation that adds an object to the collection with subsequent operations that access or remove that object to avoid memory consistency errors
BlockingQueue
- A first-in-first-out data structure
- Blocks or times out when you attempt to add to a full queue, or retrieve from an empty queue
ConcurrentMap
- A subinterface of java.util.Map
- Defines useful atomic operations
- The standard general-purpose implementation is ConcurrentHashMap
- A concurrent analog of HashMap
ConcurrentNavigableMap
- A subinterface of ConcurrentMap
- Supports approximate matches
- The standard general-purpose implementation is ConcurrentSkipListMap
- A concurrent analog of TreeMap
Atomic Variables
- The java.util.concurrent.atomic package
- Classes that support atomic operations on single variables
- The get and set methods work like reads and writes on volatile variables
- A set has a happens-before relationship with any subsequent get on the same variable
- The atomic compareAndSet method also has these memory consistency features
Simple counter
Synchronized counter
- Thread interference and liveness problems
Atomic counter
Concurrent Random Numbers
- The java.util.concurrent.ThreadLocalRandom class
- To use random numbers from multiple threads or ForkJoinTasks