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 serde::Deserialize; #[derive(Debug, Deserialize)] #[serde(untagged)]
Parsing flexible JSON shapes with serde
deserialization
enums
json
Intermediate
6 steps
ruby
require "shellwords" require "open3" module Backup
Building safe shell commands in Ruby
shell-out
subprocess
command-injection
Intermediate
7 steps
java
@Component @Converter public class EncryptedStringConverter implements AttributeConverter<String, String> {
Transparent column encryption in Spring & JPA
encryption
aes-gcm
jpa-converter
Advanced
10 steps
java
package com.acme.billing.config; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties;
Feature-flagged beans with Spring @ConditionalOnProperty
feature-flags
conditional-beans
strategy-pattern
Intermediate
5 steps
go
func (w *Watcher) resetDebounce(d time.Duration) { if !w.timer.Stop() { select { case <-w.timer.C:
Debouncing a stream of events in Go
debounce
timers
channels
Advanced
7 steps
rust
use chrono::{Duration, NaiveDate}; #[derive(Debug)] pub struct DateRange {
Parsing and iterating date ranges in Rust
error-handling
iterators
parsing
Intermediate
7 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.