Agent skill

Java Concurrency Review

by decebals in decebals/claude-code-java

Reviews Java concurrent code for thread safety, race conditions and deadlocks, and for pitfalls with Virtual Threads, CompletableFuture, ExecutorService and Spring @Async.

MITAuto-check passedDevelopment

Install Java Concurrency Review

skills CLI
$ npx skills add decebals/claude-code-java --skill concurrency-review -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install decebals/claude-code-java concurrency-review --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/decebals/claude-code-java.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/concurrency-review .claude/skills/concurrency-review && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
concurrency-review
GitHub stars
751
Token cost
~3.1k tokens
SKILL.md length
366 words
Files
2
Skills in repo
18
Repo updated
First seen
Licence
MIT

At a glance

Reviews Java concurrent code for thread safety, race conditions and deadlocks, and for pitfalls with Virtual Threads, CompletableFuture, ExecutorService and Spring @Async.

  • Works in 5 steps: Forgetting @EnableAsync → Calling Async from Same Class → @Async on Non-Public Methods → …
  • Reviewing code that uses synchronized, volatile or Lock
  • SKILL.md covers Why This Matters, When to Use, Modern Java (21/25): Virtual… and Spring @Async Pitfalls, plus 4 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

The skill is a checklist for reading multi-threaded Java. It lists the code that should trigger a review: synchronized, volatile and Lock usage, async annotations, CompletableFuture and ExecutorService, shared state and any code touched by several threads. A modern Java section explains where virtual threads suit I/O-bound work, notes that an app that never reaches 10,000 concurrent tasks may gain little, describes how Java 21 to 23 pinned virtual threads inside synchronized blocks with blocking calls and how Java 25 fixes this under JEP 491, and prefers ScopedValue over ThreadLocal and structured concurrency with StructuredTaskScope.

A Spring @Async section lists common failures: forgetting @EnableAsync so the annotation is silently ignored, calling an async method from the same class, putting it on non-public methods where the proxy cannot intercept, and relying on a default executor that creates a thread per task. The excerpt is cut off in that section, so further checks are not described here.

When your agent uses it

  • Reviewing code that uses synchronized, volatile or Lock
  • Checking thread safety of state shared between threads
  • Auditing @Async methods, CompletableFuture chains or executors
  • Reviewing Virtual Threads or structured concurrency code

Example prompts

  • “Check thread safety of the OrderCache class and point out any race conditions.”
  • “Do a concurrency review of our @Async email service.”
  • “Review this CompletableFuture pipeline for deadlocks and exception handling gaps.”
  • “Is it safe to move this service to virtual threads when it uses synchronized blocks?”

Workflow steps

5 steps, taken from the step headings in SKILL.md.

  1. Forgetting @EnableAsync
  2. Calling Async from Same Class
  3. @Async on Non-Public Methods
  4. Default Executor Creates Thread Per Task
  5. SecurityContext Not Propagating

What it can do on your machine

Read from SKILL.md and the folder at commit 0d98fe9. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are java and bash).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Java Concurrency Review loads about 3.1k tokens when it runs. Until then it costs about 71 tokens; SKILL.md has 366 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~71
When it runs · the whole SKILL.md, loaded when a task matches
~3.1k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from decebals/claude-code-java at commit 0d98fe9, republished under its MIT licence (© decebals). 366 words, ~3,059 tokens.

Download SKILL.mdSave it as .claude/skills/concurrency-review/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.
name
concurrency-review
description
Review Java concurrency code for thread safety, race conditions, deadlocks, and modern patterns (Virtual Threads, CompletableFuture, @Async). Use when user asks "check thread safety", "concurrency review", "async code review", or when reviewing multi-threaded code.
license
MIT

Concurrency Review Skill

Review Java concurrent code for correctness, safety, and modern best practices.

Why This Matters

Nearly 60% of multithreaded applications encounter issues due to improper management of shared resources. - ACM Study

Concurrency bugs are:

  • Hard to reproduce - timing-dependent
  • Hard to test - may only appear under load
  • Hard to debug - non-deterministic behavior

This skill helps catch issues before they reach production.

When to Use

  • Reviewing code with synchronized, volatile, Lock
  • Checking @Async, CompletableFuture, ExecutorService
  • Validating thread safety of shared state
  • Reviewing Virtual Threads / Structured Concurrency code
  • Any code accessed by multiple threads

Modern Java (21/25): Virtual Threads

When to Use Virtual Threads
java
// ✅ Perfect for I/O-bound tasks (HTTP, DB, file I/O)
try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
    for (Request request : requests) {
        executor.submit(() -> callExternalApi(request));
    }
}

// ❌ Not beneficial for CPU-bound tasks
// Use platform threads / ForkJoinPool instead

Rule of thumb: If your app never has 10,000+ concurrent tasks, virtual threads may not provide significant benefit.

Java 25: Synchronized Pinning Fixed

In Java 21-23, virtual threads became "pinned" when entering synchronized blocks with blocking operations. Java 25 fixes this (JEP 491).

java
// In Java 21-23: ⚠️ Could cause pinning
synchronized (lock) {
    blockingIoCall();  // Virtual thread pinned to carrier
}

// In Java 25: ✅ No longer an issue
// But consider ReentrantLock for explicit control anyway
ScopedValue Over ThreadLocal
java
// ❌ ThreadLocal problematic with virtual threads
private static final ThreadLocal<User> currentUser = new ThreadLocal<>();

// ✅ ScopedValue (Java 21+ preview, improved in 25)
private static final ScopedValue<User> CURRENT_USER = ScopedValue.newInstance();

ScopedValue.where(CURRENT_USER, user).run(() -> {
    // CURRENT_USER.get() available here and in child virtual threads
    processRequest();
});
Structured Concurrency (Java 25 Preview)
java
// ✅ Structured concurrency - tasks tied to scope lifecycle
try (StructuredTaskScope.ShutdownOnFailure scope = new StructuredTaskScope.ShutdownOnFailure()) {
    Subtask<User> userTask = scope.fork(() -> fetchUser(id));
    Subtask<Orders> ordersTask = scope.fork(() -> fetchOrders(id));

    scope.join();            // Wait for all
    scope.throwIfFailed();   // Propagate exceptions

    return new Profile(userTask.get(), ordersTask.get());
}
// All subtasks automatically cancelled if scope exits

Spring @Async Pitfalls

1. Forgetting @EnableAsync
java
// ❌ @Async silently ignored
@Service
public class EmailService {
    @Async
    public void sendEmail(String to) { }
}

// ✅ Enable async processing
@Configuration
@EnableAsync
public class AsyncConfig { }
2. Calling Async from Same Class
java
@Service
public class OrderService {

    // ❌ Bypasses proxy - runs synchronously!
    public void processOrder(Order order) {
        sendConfirmation(order);  // Direct call, not async
    }

    @Async
    public void sendConfirmation(Order order) { }
}

// ✅ Inject self or use separate service
@Service
public class OrderService {
    @Autowired
    private EmailService emailService;  // Separate bean

    public void processOrder(Order order) {
        emailService.sendConfirmation(order);  // Proxy call, async works
    }
}
3. @Async on Non-Public Methods
java
// ❌ Non-public methods - proxy can't intercept
@Async
private void processInBackground() { }

@Async
protected void processInBackground() { }

// ✅ Must be public
@Async
public void processInBackground() { }
4. Default Executor Creates Thread Per Task
java
// ❌ Default SimpleAsyncTaskExecutor - creates new thread each time!
// Can cause OutOfMemoryError under load

// ✅ Configure proper thread pool
@Configuration
@EnableAsync
public class AsyncConfig {

    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(50);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("async-");
        executor.setRejectedExecutionHandler(new CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}
5. SecurityContext Not Propagating
java
// ❌ SecurityContextHolder is ThreadLocal-bound
@Async
public void auditAction() {
    // SecurityContextHolder.getContext() is NULL here!
    String user = SecurityContextHolder.getContext().getAuthentication().getName();
}

// ✅ Use DelegatingSecurityContextAsyncTaskExecutor
@Bean
public Executor taskExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    // ... configure ...
    return new DelegatingSecurityContextAsyncTaskExecutor(executor);
}

CompletableFuture Patterns

Error Handling
java
// ❌ Exception silently swallowed
CompletableFuture.supplyAsync(() -> riskyOperation());
// If riskyOperation throws, nobody knows

// ✅ Always handle exceptions
CompletableFuture.supplyAsync(() -> riskyOperation())
    .exceptionally(ex -> {
        log.error("Operation failed", ex);
        return fallbackValue;
    });

// ✅ Or use handle() for both success and failure
CompletableFuture.supplyAsync(() -> riskyOperation())
    .handle((result, ex) -> {
        if (ex != null) {
            log.error("Failed", ex);
            return fallbackValue;
        }
        return result;
    });
Timeout Handling (Java 9+)
java
// ✅ Fail after timeout
CompletableFuture.supplyAsync(() -> slowOperation())
    .orTimeout(5, TimeUnit.SECONDS);  // Throws TimeoutException

// ✅ Return default after timeout
CompletableFuture.supplyAsync(() -> slowOperation())
    .completeOnTimeout(defaultValue, 5, TimeUnit.SECONDS);
Combining Futures
java
// ✅ Wait for all
CompletableFuture.allOf(future1, future2, future3)
    .thenRun(() -> log.info("All completed"));

// ✅ Wait for first
CompletableFuture.anyOf(future1, future2, future3)
    .thenAccept(result -> log.info("First result: {}", result));

// ✅ Combine results
future1.thenCombine(future2, (r1, r2) -> merge(r1, r2));
Use Appropriate Executor
java
// ❌ CPU-bound task in ForkJoinPool.commonPool (default)
CompletableFuture.supplyAsync(() -> cpuIntensiveWork());

// ✅ Custom executor for blocking/I/O operations
ExecutorService ioExecutor = Executors.newFixedThreadPool(20);
CompletableFuture.supplyAsync(() -> blockingIoCall(), ioExecutor);

// ✅ In Java 21+, virtual threads for I/O
ExecutorService virtualExecutor = Executors.newVirtualThreadPerTaskExecutor();
CompletableFuture.supplyAsync(() -> blockingIoCall(), virtualExecutor);

Classic Concurrency Issues

Race Conditions: Check-Then-Act
java
// ❌ Race condition
if (!map.containsKey(key)) {
    map.put(key, computeValue());  // Another thread may have added it
}

// ✅ Atomic operation
map.computeIfAbsent(key, k -> computeValue());

// ❌ Race condition with counter
if (count < MAX) {
    count++;  // Read-check-write is not atomic
}

// ✅ Atomic counter
AtomicInteger count = new AtomicInteger();
count.updateAndGet(c -> c < MAX ? c + 1 : c);
Visibility: Missing volatile
java
// ❌ Other threads may never see the update
private boolean running = true;

public void stop() {
    running = false;  // May not be visible to other threads
}

public void run() {
    while (running) { }  // May loop forever
}

// ✅ Volatile ensures visibility
private volatile boolean running = true;
Non-Atomic long/double
java
// ❌ 64-bit read/write is non-atomic on 32-bit JVMs
private long counter;

public void increment() {
    counter++;  // Not atomic!
}

// ✅ Use AtomicLong or synchronization
private AtomicLong counter = new AtomicLong();

// ✅ Or volatile (for single-writer scenarios)
private volatile long counter;
Double-Checked Locking
java
// ❌ Broken without volatile
private static Singleton instance;

public static Singleton getInstance() {
    if (instance == null) {
        synchronized (Singleton.class) {
            if (instance == null) {
                instance = new Singleton();  // May be seen partially constructed
            }
        }
    }
    return instance;
}

// ✅ Correct with volatile
private static volatile Singleton instance;

// ✅ Or use holder class idiom
private static class Holder {
    static final Singleton INSTANCE = new Singleton();
}

public static Singleton getInstance() {
    return Holder.INSTANCE;
}
Deadlocks: Lock Ordering
java
// ❌ Potential deadlock
// Thread 1: lock(A) -> lock(B)
// Thread 2: lock(B) -> lock(A)

public void transfer(Account from, Account to, int amount) {
    synchronized (from) {
        synchronized (to) {
            // Transfer logic
        }
    }
}

// ✅ Consistent lock ordering
public void transfer(Account from, Account to, int amount) {
    Account first = from.getId() < to.getId() ? from : to;
    Account second = from.getId() < to.getId() ? to : from;

    synchronized (first) {
        synchronized (second) {
            // Transfer logic
        }
    }
}

Thread-Safe Collections

Show full SKILL.md (153 more words)Show less
Choose the Right Collection
Use CaseWrongRight
Concurrent reads/writesHashMapConcurrentHashMap
Frequent iterationConcurrentHashMapCopyOnWriteArrayList
Producer-consumerArrayListBlockingQueue
Sorted concurrentTreeMapConcurrentSkipListMap
ConcurrentHashMap Pitfalls
java
// ❌ Non-atomic compound operation
if (!map.containsKey(key)) {
    map.put(key, value);
}

// ✅ Atomic
map.putIfAbsent(key, value);
map.computeIfAbsent(key, k -> createValue());

// ❌ Nested compute can deadlock
map.compute(key1, (k, v) -> {
    return map.compute(key2, ...);  // Deadlock risk!
});

Concurrency Review Checklist

🔴 High Severity (Likely Bugs)
  • No check-then-act on shared state without synchronization
  • No synchronized calling external/unknown code (deadlock risk)
  • volatile present for double-checked locking
  • Non-volatile fields not read in loops waiting for updates
  • ConcurrentHashMap.compute() doesn't call other map operations
  • @Async methods are public and called from different beans
🟡 Medium Severity (Potential Issues)
  • Thread pools properly sized and named
  • CompletableFuture exceptions handled (exceptionally/handle)
  • SecurityContext propagated to async tasks if needed
  • ExecutorService properly shut down
  • Lock.unlock() in finally block
  • Thread-safe collections used for shared data
🟢 Modern Patterns (Java 21/25)
  • Virtual threads used for I/O-bound concurrent tasks
  • ScopedValue considered over ThreadLocal
  • Structured concurrency for related subtasks
  • Timeouts on CompletableFuture operations
📝 Documentation
  • Thread safety documented on shared classes
  • Locking order documented for nested locks
  • Each volatile usage justified

Analysis Commands

bash
# Find synchronized blocks
grep -rn "synchronized" --include="*.java"

# Find @Async methods
grep -rn "@Async" --include="*.java"

# Find volatile fields
grep -rn "volatile" --include="*.java"

# Find thread pool creation
grep -rn "Executors\.\|ThreadPoolExecutor\|ExecutorService" --include="*.java"

# Find CompletableFuture without error handling
grep -rn "CompletableFuture\." --include="*.java" | grep -v "exceptionally\|handle\|whenComplete"

# Find ThreadLocal (consider ScopedValue in Java 21+)
grep -rn "ThreadLocal" --include="*.java"

© decebals, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 1 other file in skills/concurrency-review of decebals/claude-code-java.

  • SKILL.md
  • README.md

Open the folder on GitHubat commit 0d98fe9

Compare with similar skills

Java Concurrency Review next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Java Concurrency Review compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Java Concurrency Review this skilldecebals/claude-code-java751—~3.1kAutomated safety check: PassMIT
Code Review Skillawesome-skills/code-review-skill2.1k—~2.8kAutomated safety check: NotesMIT
Git History Bug Auditben-manes/caffeine18k—~3.3kAutomated safety check: PassApache-2.0
Cross-Language Coding Standardszereight/gitlab-mcp2k1 repos~1.4kAutomated safety check: PassMIT
Code Qualitypiomin/claude-ai-spring-boot1.3k—~2.2kAutomated safety check: PassApache-2.0
Adversarial Codebase Auditben-manes/caffeine18k—~1.9kAutomated safety check: NotesApache-2.0

Similar skills

  • Code Review Skill

    awesome-skills/code-review-skill

    Provides comprehensive code review guidance for React 19, Vue 3, Angular 17+, Svelte 5, Rust, TypeScript, Java, Java 8, PHP, Ruby, Rails, Python, Django, FastAPI, Go, C/.NET, Kotlin, Swift, Dart…

    2.1k GitHub stars~2.8k tokensUpdated 1 mo ago
    DevelopmentAuto-check: notes
  • Git History Bug Audit

    ben-manes/caffeine

    Audits a module by walking its git history commit by commit, tracking unresolved issues forward, and reporting the ones that survive to HEAD as findings.

    18k GitHub stars~3.3k tokensUpdated today
    DevelopmentAuto-check passed
  • Shared reference for naming, function size, complexity and error handling rules that reviewer agents apply across TypeScript, Python, Go, Rust, Java, C# and Swift.

    2k GitHub starsUsed in 1 repo~1.4k tokens
    DevelopmentAuto-check passed
  • Code Quality

    piomin/claude-ai-spring-boot

    Comprehensive code review for Java - clean code principles, API contracts, null safety, exception handling, and performance.

    1.3k GitHub stars~2.2k tokensUpdated 5 mo ago
    DevelopmentAuto-check passed
  • Adversarial Codebase Audit

    ben-manes/caffeine

    Runs a hostile review of the Caffeine Java caching library with parallel subagents that get no design docs, then challenges and consolidates their findings.

    18k GitHub stars~1.9k tokensUpdated today
    DevelopmentAuto-check: notes
  • Audit Sibling Divergence

    ben-manes/caffeine

    Compares code paths that should behave the same, such as sync and async cache methods, and requires a concrete scenario where the two observably disagree.

    18k GitHub stars~4.6k tokensUpdated today
    DevelopmentAuto-check: notes

More from decebals/claude-code-java

All 18 skills in this repo
  • Java Design Patterns Reference

    decebals/claude-code-java

    A practical Java reference for Builder, Factory, Singleton, Strategy, Observer and other patterns, with a table matching problems to patterns.

    751 GitHub starsUsed in 1 repo~4.4k tokens
    Auto-check passed
  • Jpa Patterns

    decebals/claude-code-java

    JPA/Hibernate patterns and common pitfalls (N+1, lazy loading, transactions, queries).

    751 GitHub starsUsed in 1 repo~4k tokens
    Auto-check passed
  • Logging Patterns

    decebals/claude-code-java

    Java logging best practices with SLF4J, structured logging (JSON), and MDC for request tracing.

    751 GitHub starsUsed in 1 repo~3.3k tokens
    Auto-check passed
  • REST API Contract Review

    decebals/claude-code-java

    Reviews REST API design for correct HTTP verbs, versioning, DTO use, consistent responses and backward compatibility before an API change ships.

    751 GitHub stars~2.8k tokensUpdated 1 mo ago
    Auto-check passed
  • Java Architecture Review

    decebals/claude-code-java

    Reviews a Java project's architecture at the macro level: package structure, module boundaries, dependency direction and layering.

    751 GitHub stars~2.2k tokensUpdated 1 mo ago
    Auto-check passed
  • Changelog Generator for Java

    decebals/claude-code-java

    Builds changelog entries from conventional commits in a Java project, after working out whether it uses SemVer, two-part versions or calendar versions.

    751 GitHub stars~2.1k tokensUpdated 1 mo ago
    Auto-check passed

Works with

Categories

Questions about Java Concurrency Review

What does Java Concurrency Review do?

Reviews Java concurrent code for thread safety, race conditions and deadlocks, and for pitfalls with Virtual Threads, CompletableFuture, ExecutorService and Spring @Async. The skill is a checklist for reading multi-threaded Java. It lists the code that should trigger a review: synchronized, volatile and Lock usage, async annotations, CompletableFuture and ExecutorService, shared state and any code touched by several threads.

When should I use Java Concurrency Review?

Java Concurrency Review fits situations like: reviewing code that uses synchronized, volatile or Lock; checking thread safety of state shared between threads; auditing @Async methods, CompletableFuture chains or executors; reviewing Virtual Threads or structured concurrency code.

How do I install Java Concurrency Review in Claude Code?

Run `npx skills add decebals/claude-code-java --skill concurrency-review -a claude-code`. Or copy the skill folder (skills/concurrency-review in decebals/claude-code-java) into .claude/skills/concurrency-review in your project. Claude Code loads it when a task matches its description.

How do I install Java Concurrency Review in Codex?

Run `npx skills add decebals/claude-code-java --skill concurrency-review -a codex`. Or copy the skill folder (skills/concurrency-review in decebals/claude-code-java) into .agents/skills/concurrency-review in your project. Codex loads it when a task matches its description.

Can I use Java Concurrency Review in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add decebals/claude-code-java --skill concurrency-review -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/concurrency-review, .gemini/skills/concurrency-review, .github/skills/concurrency-review and .opencode/skills/concurrency-review in your project.

What does Java Concurrency Review need to run?

SKILL.md names no scripts, command-line tools or credentials: Java Concurrency Review is instructions for the agent only.

Does Java Concurrency Review access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Java Concurrency Review safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Java Concurrency Review use?

Java Concurrency Review is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Java Concurrency Review use?

About 3.1k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Java Concurrency Review?

Skills that share tags, products or a category with Java Concurrency Review: Code Review Skill (awesome-skills/code-review-skill, 2.1k stars), Git History Bug Audit (ben-manes/caffeine, 18k stars), Cross-Language Coding Standards (zereight/gitlab-mcp, 2k stars) and Code Quality (piomin/claude-ai-spring-boot, 1.3k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Java Concurrency Review?

decebals (a GitHub user) maintains it in decebals/claude-code-java, which has 751 GitHub stars. The repository holds 18 skills in this directory. The repository was last updated on September 6, 2026.

Source: decebals/claude-code-java on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.