Concurrent layer
- Java course
- Advanced
- Lesson 75/82
- 6 min
Write parallel operations with ExecutorService.
Tasks with ExecutorService
In this lesson you will run a task concurrently with ExecutorService. Executors.newSingleThreadExecutor() creates a single-thread pool; submit takes a Callable and returns a Future.
ExecutorService pool = Executors.newSingleThreadExecutor();
Future<Integer> future = pool.submit(task);
int total = future.get();
pool.shutdown();future.get() blocks until the task completes and returns the result. In a single-thread pool the output order is deterministic, so the expected output is the same every time. When done, close the pool with shutdown.
Callable and Future
Callable<V> is a task that returns a result; its call() method returns a value of type V. Future<V> holds a result that will appear later; .get() blocks until it is ready.
Callable<Integer> task = () -> {
int sum = 0;
for (Transaction t : ledger) sum += t.amount;
return sum;
};This task sums all amounts in the list. You run it with submit(task) and get the result with future.get(). The lambda implements Callable's single method automatically.
Practice Compute the concurrent total
Use the previous lesson's ledger list. Create the pool with ExecutorService pool = Executors.newSingleThreadExecutor();. Write a Callable<Integer> task lambda that sums all amounts in the list. Get the result with pool.submit(task).get() and print it with System.out.println. Finally call pool.shutdown().
Starter code
import java.util.ArrayList;
import java.util.concurrent.*;
class Transaction {
String category;
int amount;
Transaction(String category, int amount) {
this.category = category;
this.amount = amount;
}
}
public class Main {
public static void main(String[] args) throws Exception {
ArrayList<Transaction> ledger = new ArrayList<>();
ledger.add(new Transaction("market", 120));
ledger.add(new Transaction("fuel", 80));
var filtered = ledger.stream()
.filter(t -> t.amount > 100)
.toList();
// Submit a Callable via ExecutorService and return the total
}
}Sample solution
import java.util.ArrayList;
import java.util.concurrent.*;
class Transaction {
String category;
int amount;
Transaction(String category, int amount) {
this.category = category;
this.amount = amount;
}
}
public class Main {
public static void main(String[] args) throws Exception {
ArrayList<Transaction> ledger = new ArrayList<>();
ledger.add(new Transaction("market", 120));
ledger.add(new Transaction("fuel", 80));
var filtered = ledger.stream()
.filter(t -> t.amount > 100)
.toList();
ExecutorService pool = Executors.newSingleThreadExecutor();
Callable<Integer> task = () -> {
int sum = 0;
for (Transaction t : ledger) sum += t.amount;
return sum;
};
Future<Integer> future = pool.submit(task);
int total = future.get();
pool.shutdown();
System.out.println(total);
}
}Expected output
200
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 What does ExecutorService replace?
- A class definition
- A stream operation
- Hand-creating a Thread Correct answer
- Writing tests
Explanation: ExecutorService replaces direct new Thread usage.
2 Complete the submit call
ExecutorService pool = Executors.newSingleThreadExecutor();
Future<Integer> future = pool.____(task);
ExecutorService pool = Executors.newSingleThreadExecutor();
Future<Integer> future = pool.submit(task);
Explanation: submit takes a Callable and returns a Future.
3 Match the concurrent concepts
| Term | Meaning |
|---|---|
ExecutorService |
Task pool |
Callable |
Result-bearing task |
Future |
Pending result |
submit |
Sends the task |