Study guide
13.3 The Concurrency Framework: `ExecutorService`, Thread Pools, and `Future`
Oracle Java SE 17 Developer Certified Professional 1Z0-829
Track your progress as you read
Finished sections get a check mark.
1 Introduction: The 1Z0-829 Exam
About the Java SE 17 Developer (1Z0-829) Exam
2 Chapter 1: Java Fundamentals & Language Basics
1.1 Primitive Types, Literals, Wrapper Classes, and Type Promotion/Casting 1.2 Local Variable Type Inference (`var`) Rules and Scoping 1.3 Operators, Precedence, Evaluation Order, and Short-Circuit Evaluation 1.4 Text Blocks, String Immutability, and StringBuilder APIs
3 Chapter 2: Program Flow & Decision Constructs
2.1 Conditional Branching with if/else and the Ternary Operator 2.2 Switch Statements and Switch Expressions 2.3 Iteration Constructs, Loop Control, and Branching Labels
4 Chapter 3: Object-Oriented Design & Class Mechanics
3.1 Class Declarations, Field/Method Signatures, and Access Modifiers 3.2 Constructors, Overloading, Initialization Order, and Garbage Collection 3.3 Inheritance, Method Overriding, Polymorphism, and `super`/`this` 3.4 Abstract Classes, Static Members, and Object Methods (`equals`, `hashCode`, `toString`)
5 Chapter 4: Advanced OOP: Interfaces, Records & Sealed Types
4.1 Interface Architecture: Default, Static, and Private Methods 4.2 Enumerations: Constants, Constructors, Methods, and Custom Bodies 4.3 Records: Canonical/Compact Constructors, Components, and Immutability 4.4 Sealed Classes and Interfaces: `permits`, Hierarchy Constraints, and Modifiers
6 Chapter 5: Pattern Matching & Nested Types
5.1 Pattern Matching for `instanceof` and Flow Scoping Mechanics 5.2 Nested Types: Member Inner, Static Nested, Local, and Anonymous Classes 5.3 Defensive Programming, Immutability Patterns, and Validation
7 Chapter 6: Generics, Collections & Arrays
6.1 Generic Classes, Interfaces, Methods, and Type Erasure 6.2 Bounded Type Parameters and Wildcards (PECS Rule) 6.3 Collections Framework: List, Set, Queue, and Deque APIs 6.4 The Map Interface, Sorting, Comparable, and Comparator 6.5 Arrays: Declaration, Initialization, Multidimensional Arrays, and the Arrays Utility Class
8 Chapter 7: Functional Programming & Lambda Expressions
7.1 Functional Interfaces and Lambda Syntax Rules 7.2 Standard Functional Interfaces in `java.util.function` 7.3 Method References: Static, Bound, Unbound, and Constructor References
9 Chapter 8: The Stream API
8.1 Stream Lifecycle: Creation, Pipeline Architecture, and Lazy Evaluation 8.2 Intermediate Stream Operations: Filtering, Mapping, Sorting, and Slicing 8.3 Terminal Stream Operations: Reduction, Matching, Finding, and Collecting 8.4 Primitive Streams (`IntStream`, `LongStream`, `DoubleStream`) and Numeric Statistics
10 Chapter 9: Advanced Streams & Collectors
9.1 The Optional Class: Safe Null Handling, Transformation, and Chaining 9.2 The Collectors API: Downstream Reductions, Grouping, and Partitioning 9.3 Parallel Streams: Fork/Join Pool, Spliterators, and Concurrency Pitfalls
11 Chapter 10: Exception Handling
10.1 The Java Exception Hierarchy: Checked vs. Unchecked Exceptions and Errors 10.2 Exception Constructs: `try-catch-finally`, Multi-Catch, and Rethrowing 10.3 Try-With-Resources, `AutoCloseable`, Suppressed Exceptions, and Custom Exceptions
12 Chapter 11: Date/Time API & Localization
11.1 Date and Time Core Types: `LocalDate`, `LocalTime`, `LocalDateTime` 11.2 Timestamps, Intervals, and Durations: `Instant`, `Period`, and `Duration` 11.3 Time Zones, Daylight Saving Time (DST) Offsets, and `ZonedDateTime` 11.4 Internationalization and Localization: `Locale`, `ResourceBundle`, and Formatters 11.5 Formatting and Parsing Messages, Numbers, Percentages, and Localized Dates
13 Chapter 12: Java Platform Module System (JPMS)
12.1 Module Architecture, `module-info.java`, and Module Paths 12.2 Module Directives: `requires`, `requires transitive`, `exports`, and Qualified Exports 12.3 Reflection, Deep Encapsulation, `opens`, and Open Modules 12.4 Services in JPMS (`uses`, `provides...with`), Migration Paths, and Tooling (`jlink`, `jdeps`) 12.5 Compiling and Packaging Code: Non-Modular JARs, Modular JARs, and Migration Strategies
14 Chapter 13: Concurrency & Multithreading
13.1 Thread Fundamentals, `Runnable`, `Callable`, and Thread Lifecycle 13.2 Memory Visibility, `volatile`, Intrinsic Locks, and Synchronization 13.3 The Concurrency Framework: `ExecutorService`, Thread Pools, and `Future` 13.4 Concurrent Collections, Atomic Variables, Explicit Locks, and `CompletableFuture`
15 Chapter 14: Java I/O and NIO.2
14.1 Classical I/O: Byte and Character Streams, Readers, Writers, and Buffering 14.2 Object Serialization, `Serializable`, `transient`, and `serialVersionUID` 14.3 NIO.2 Architecture: `Path`, `Paths`, and Basic `Files` Operations 14.4 Advanced NIO.2: Directory Walking, Streams (`Files.lines`, `walk`), and `WatchService`
16 Chapter 15: Accessing Databases with JDBC
15.1 JDBC Architecture, Drivers, `DriverManager`, and `DataSource` Connections 15.2 SQL Execution: `Statement`, `PreparedStatement`, and `CallableStatement` 15.3 `ResultSet` Navigation, Data Types, and Transaction Management (Commit, Rollback, Savepoints)
17 Chapter 16: Annotations & the Java Logging API
16.1 Standard Annotations: @Override, @FunctionalInterface, @Deprecated, @SuppressWarnings, and @SafeVarargs 16.2 Java Logging API Basics: Logger, Levels, Handlers, and Configuration
13.3 The Concurrency Framework: `ExecutorService`, Thread Pools, and `Future`
Key Takeaways Explain This Topic AI
The Executor framework decouples task submission from execution mechanics, eliminating thread creation overhead and thread exhaustion through managed pools.
The Executors utility class supplies standard pool configurations, including newFixedThreadPool, newCachedThreadPool, newSingleThreadExecutor, and newScheduledThreadPool.
Tasks submitted via execute() run fire-and-forget returning void, whereas submit() accepts Runnable or Callable and returns a Future to monitor and control task execution.
Calling Future.get() blocks the calling thread until computation completes and wraps task exceptions inside an ExecutionException.
shutdown() ceases acceptance of new tasks while completing existing work, whereas shutdownNow() actively interrupts running threads and drains pending tasks from the queue.
Last updated: October 2026
The Concurrency Framework: ExecutorService , Thread Pools, and Future
Manually creating and managing Thread instances in production applications creates severe architectural bottlenecks. Each thread allocation incurs operating system memory overhead and context-switching penalties. Unbounded thread instantiation under heavy load leads to resource exhaustion and OutOfMemoryError: unable to create new native thread . Java solves this through the Executor Framework in java.util.concurrent , which decouples task specification from thread management and provides thread pooling, lifecycle control, and asynchronous result retrieval.
The Executor Hierarchy
The framework is structured across three core interfaces: +-----------------------------------------------------------+
- | Executor |
- | void execute(Runnable command) |
- +-----------------------------------------------------------+
- ^
- |
- +-----------------------------------------------------------+
- | ExecutorService |
- | <T> Future<T> submit(Callable<T> task) |
- | Future<?> submit(Runnable task) |
- | void shutdown() / List<Runnable> shutdownNow() |
- | List<Future<T>> invokeAll(Collection<Callable<T>> tasks)|
- | T invokeAny(Collection<Callable<T>> tasks) |
- +-----------------------------------------------------------+
- ^
- |
- +-----------------------------------------------------------+
- | ScheduledExecutorService |
- | schedule(...) |
- | scheduleAtFixedRate(...) |
- | scheduleWithFixedDelay(...) |
- +-----------------------------------------------------------+
Executor : The foundational root interface providing a single method: void execute(Runnable command) . It models a fire-and-forget submission model.
ExecutorService : Extends Executor , adding robust lifecycle management ( shutdown , shutdownNow ), task submission returning Future instances, and batch execution capabilities ( invokeAll , invokeAny ).
ScheduledExecutorService : Extends ExecutorService to support one-shot delayed execution and periodic recurring task execution.
Thread Pool Factories in Executors
The java.util.concurrent.Executors utility class provides static factory methods for creating pre-configured thread pools: ExecutorService single = Executors.newSingleThreadExecutor();
- ExecutorService fixed = Executors.newFixedThreadPool(4);
- ExecutorService cached = Executors.newCachedThreadPool();
- ScheduledExecutorService sched = Executors.newScheduledThreadPool(2);
- Factory Method Core / Max Threads Work Queue Type Idle Thread Timeout Common Use Case
- newSingleThreadExecutor() 1 / 1 Unbounded LinkedBlockingQueue N/A Strictly sequential background execution
newFixedThreadPool(n) n / n Unbounded LinkedBlockingQueue None (retained) Predictable, CPU-bounded resource limits
newCachedThreadPool() 0 / Integer.MAX_VALUE SynchronousQueue (direct handoff) 60 seconds High-volume, short-lived asynchronous tasks
newScheduledThreadPool(n) n / Integer.MAX_VALUE Delayed work queue None (for core) Recurring maintenance and polling schedules
Note
newSingleThreadExecutor() guarantees that if the single worker thread terminates abruptly due to a failure during task execution, a new worker thread is automatically created to replace it for subsequent tasks.
Submitting Tasks: execute() vs. submit()
An ExecutorService accepts tasks through several methods:
execute(Runnable) : Defined in Executor . It returns void . If the task throws an uncaught runtime exception, it terminates the executing worker thread and propagates to the thread's UncaughtExceptionHandler .
submit(Runnable) : Defined in ExecutorService . It returns a Future<?> . Upon successful completion, calling future.get() returns null . Any uncaught exception thrown during task execution is captured and re-thrown inside an ExecutionException when get() is called.
submit(Callable<T>) : Returns a Future<T> . When the task completes, future.get() yields the returned value of type T .
submit(Runnable, T result) : Returns a Future<T> that produces the predetermined result object upon task completion.
Managing Asynchronous Results with Future<T>
A Future<T> represents the lifecycle and deferred result of an asynchronous computation: ExecutorService executor = Executors.newSingleThreadExecutor();
- Future<Integer> future = executor.submit(() -> {
- Thread.sleep(1000);
- return 42;
- });
System.out.println("Is completed? " + future.isDone()); // false
Integer result = future.get(); // BLOCKS until calculation finishes!
- System.out.println("Calculated: " + result); // 42
- executor.shutdown();
- Core Future API Methods
V get() : Blocks the calling thread indefinitely until the task completes. Throws InterruptedException (if the waiting thread is interrupted) and ExecutionException (if the underlying computation threw an exception).
V get(long timeout, TimeUnit unit) : Blocks up to the specified duration. If the task does not finish within that window, it throws TimeoutException without cancelling the task.
boolean isDone() : Non-blocking query returning true if the task completed normally, threw an exception, or was cancelled.
boolean isCancelled() : Returns true if the task was cancelled before completing.
boolean cancel(boolean mayInterruptIfRunning) : Attempts to abort execution. If mayInterruptIfRunning is true , the thread executing the task is sent an interrupt() request.
Batch Task Execution: invokeAll() vs. invokeAny()
ExecutorService simplifies multi-task orchestration through two batch methods:
invokeAll()
Executes a collection of Callable tasks, blocking until all tasks complete (either normally or exceptionally). It returns a List<Future<T>> in the exact iteration order of the original task collection. Every returned Future is guaranteed to have isDone() == true .
invokeAny()
Executes a collection of Callable tasks and blocks until any one task completes successfully (without throwing an exception). It returns the value of that first successful task and cancels all remaining uncompleted tasks. If all tasks fail, an ExecutionException is thrown.
Scheduling Tasks with ScheduledExecutorService ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
1. schedule(Callable/Runnable, long delay, TimeUnit unit)
Executes a task once after the specified delay elapses.
2. scheduleAtFixedRate(command, initialDelay, period, unit)
Schedules periodic execution where the target start time of execution n + 1 n+1 n + 1 is calculated strictly as initialDelay + (n * period) . If a task execution takes longer than period , the subsequent execution begins immediately upon completion—executions never run concurrently on the same schedule, but execution times will not drift.
3. scheduleWithFixedDelay(command, initialDelay, delay, unit)
Schedules periodic execution where a fixed delay occurs between the completion of execution n n n and the commencement of execution n + 1 n+1 n + 1 . The interval between executions is always executionDuration + delay .
Warning
Periodic Exception Suppression If any execution of a periodic task in scheduleAtFixedRate or scheduleWithFixedDelay throws an uncaught exception, subsequent executions are silently suppressed and cancelled . Always wrap periodic task logic in robust try-catch blocks.
Graceful Shutdown and Lifecycle States
An ExecutorService does not terminate automatically when tasks finish; its worker threads remain active, preventing JVM shutdown unless closed explicitly. ExecutorService executor = Executors.newFixedThreadPool(2);
// submit tasks...
- executor.shutdown(); // Reject new submissions, finish existing tasks
- try {
- if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
- List<Runnable> droppedTasks = executor.shutdownNow(); // Force cancel
- }
- } catch (InterruptedException e) {
- executor.shutdownNow();
- Thread.currentThread().interrupt();
- }
shutdown() : Stops accepting new tasks. Any subsequent call to submit() or execute() throws RejectedExecutionException . Already accepted tasks (both active and waiting in queue) continue to execution.
shutdownNow() : Attempts to stop actively executing tasks via Thread.interrupt() , drains all awaiting tasks from the work queue, and returns them as a List<Runnable> .
isShutdown() : Returns true immediately after shutdown() or shutdownNow() has been invoked.
isTerminated() : Returns true only after all tasks have completed and all worker threads have stopped.