java
40 lines · 7 steps
Bounded parallel thumbnail rendering in Java
A fixed thread pool renders thumbnails concurrently while each task's result is collected with a timeout and per-item error handling.
Explained by
highlit
1public class ThumbnailProcessor {
2
3 private static final int MAX_CONCURRENCY = 4;
4
5 private final ExecutorService executor = Executors.newFixedThreadPool(MAX_CONCURRENCY);
6 private final ThumbnailGenerator generator;
7
8 public ThumbnailProcessor(ThumbnailGenerator generator) {
9 this.generator = generator;
10 }
11
12 public Map<String, byte[]> processAll(List<URI> sources) throws InterruptedException {
13 Map<URI, Future<byte[]>> pending = new LinkedHashMap<>();
14
15 for (URI source : sources) {
16 pending.put(source, executor.submit(() -> generator.render(source)));
17 }
18
19 Map<String, byte[]> results = new LinkedHashMap<>();
20 for (Map.Entry<URI, Future<byte[]>> entry : pending.entrySet()) {
21 String key = entry.getKey().toString();
22 try {
23 results.put(key, entry.getValue().get(30, TimeUnit.SECONDS));
24 } catch (TimeoutException e) {
25 entry.getValue().cancel(true);
26 log.warn("Thumbnail timed out for {}", key);
27 } catch (ExecutionException e) {
28 log.error("Thumbnail failed for {}", key, e.getCause());
29 }
30 }
31 return results;
32 }
33
34 public void shutdown() throws InterruptedException {
35 executor.shutdown();
36 if (!executor.awaitTermination(1, TimeUnit.MINUTES)) {
37 executor.shutdownNow();
38 }
39 }
40}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1A fixed thread pool caps how many tasks run at once, protecting the machine from unbounded parallelism.
- 2Submitting all work first and then collecting Futures lets independent tasks overlap instead of running one at a time.
- 3Per-future timeouts and try/catch keep one slow or failing task from sinking the entire batch.
Related explainers
rust
use std::collections::HashMap; use std::sync::{Arc, Mutex}; use std::thread;
Aggregating metrics across threads in Rust
concurrency
shared-state
mutex
Intermediate
7 steps
go
package main import ( "errors"
Parsing and validating CLI flags in Go
cli-parsing
validation
error-handling
Intermediate
8 steps
typescript
type RetryOptions = { retries?: number; timeoutMs?: number; baseDelayMs?: number;
Retry with timeout and backoff in TypeScript
promises
retry
exponential-backoff
Intermediate
10 steps
rust
use std::sync::{mpsc, Arc, Mutex}; use std::thread; use std::time::Duration;
Building a thread pool in Rust
concurrency
channels
thread-pool
Advanced
9 steps
java
public class SortedListMerger { public static int[] merge(int[] a, int[] b) { int[] result = new int[a.length + b.length];
Merging two sorted arrays in Java
two-pointers
merging
arrays
Beginner
6 steps
go
package cache import ( "container/list"
Building a generic LRU cache in Go
lru-cache
generics
linked-list
Intermediate
8 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/bounded-parallel-thumbnail-rendering-in-java-explained-java-d771/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.