Java并发
Mattakushi4322026-10-25查看 596复制 866
何时激活:Java并发、CompletableFuture、ExecutorService、虚拟线程、synchronized、ReentrantLock、原子、线程安全
📘如何使用这个技能
- 1复制技能内容·点击上方「Copy SKILL.md」复制全部内容,或 Download 下载到本地
- 2打开你的 AI 客户端·支持 Claude Code、Trae、Cursor、ChatGPT、DeepSeek、Kimi 等任意 AI 助手
- 3粘贴为系统提示/知识文件·Claude Code:放入 .claude/skills/ 目录;普通对话:作为首条消息发送并说「请严格按这份技能文档执行」
- 4直接提出你的需求·AI 会按技能定义的工作流、格式和约束来处理,无需再解释背景
💡 提示:技能生效后,每次对话只需一句需求,AI 会按 SKILL.md 的流程执行。
SKILL.md5357 chars
---
name: java-concurrency
description: "When to activate: Java concurrency, CompletableFuture, ExecutorService, virtual threads, synchronized, ReentrantLock, atomic, thread safety"
origin: zakr
metadata:
namespace: zakr/devtools-pack
version: 1.0.0
category: engineering
language: java-kotlin
platforms: [claude-code, codex, gemini-cli, cursor, aider, windsurf]
---
# Java Concurrency Patterns
## Virtual Threads (Java 21)
```java
// Per-request virtual thread — cheap, blocks are fine
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
executor.submit(() -> handleRequest(req));
}
// Spring Boot 3.2+ — enable globally
// spring.threads.virtual.enabled=true
// Structured concurrency (preview)
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
Future<User> user = scope.fork(() -> userApi.getUser(id));
Future<List<Order>> orders = scope.fork(() -> orderApi.getOrders(id));
scope.join().throwIfFailed();
return new UserWithOrders(user.get(), orders.get());
}
```
## CompletableFuture
```java
// Chain async operations
CompletableFuture<UserDto> result = CompletableFuture
.supplyAsync(() -> userRepo.findById(id), executor)
.thenApply(User::toDto)
.thenCompose(dto -> enrichWithOrders(dto))
.exceptionally(ex -> {
log.warn("Failed to load user {}", id, ex);
return UserDto.empty();
});
// Parallel fetch, combine results
var userFuture = CompletableFuture.supplyAsync(() -> userApi.get(id), executor);
var orderFuture = CompletableFuture.supplyAsync(() -> orderApi.list(id), executor);
CompletableFuture.allOf(userFuture, orderFuture)
.thenApply(v -> new Dashboard(userFuture.join(), orderFuture.join()))
.get(5, TimeUnit.SECONDS);
// Timeout
CompletableFuture.supplyAsync(this::slowOp)
.orTimeout(3, TimeUnit.SECONDS)
.exceptionally(ex -> fallback());
```
## ExecutorService
```java
// Fixed pool for CPU-bound work
ExecutorService cpuPool = Executors.newFixedThreadPool(
Runtime.getRuntime().availableProcessors());
// Bounded queue prevents OOM under load
ExecutorService bounded = new ThreadPoolExecutor(
4, 16,
60L, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(1000),
new ThreadFactory() {
private final AtomicInteger count = new AtomicInteger();
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "worker-" + count.incrementAndGet());
t.setDaemon(true);
return t;
}
},
new ThreadPoolExecutor.CallerRunsPolicy() // backpressure
);
// Always shut down
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
cpuPool.shutdown();
try { cpuPool.awaitTermination(30, TimeUnit.SECONDS); }
catch (InterruptedException e) { Thread.currentThread().interrupt(); }
}));
```
## Locks & Conditions
```java
public class BoundedBuffer<T> {
private final Lock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
private final Queue<T> queue;
private final int capacity;
public void put(T item) throws InterruptedException {
lock.lock();
try {
while (queue.size() == capacity) notFull.await();
queue.add(item);
notEmpty.signal();
} finally { lock.unlock(); }
}
public T take() throws InterruptedException {
lock.lock();
try {
while (queue.isEmpty()) notEmpty.await();
T item = queue.poll();
notFull.signal();
return item;
} finally { lock.unlock(); }
}
}
```
## Atomic Operations
```java
// AtomicLong for counters — no synchronized needed
private final AtomicLong requestCount = new AtomicLong();
requestCount.incrementAndGet();
// AtomicReference for lock-free state updates
private final AtomicReference<Config> configRef = new AtomicReference<>(Config.DEFAULT);
configRef.updateAndGet(old -> old.withTimeout(newTimeout));
// CAS pattern
AtomicInteger state = new AtomicInteger(0);
boolean acquired = state.compareAndSet(0, 1); // only one thread succeeds
```
## ConcurrentCollections
```java
// Thread-safe map — prefer over Collections.synchronizedMap
ConcurrentHashMap<String, User> cache = new ConcurrentHashMap<>();
cache.computeIfAbsent(key, k -> loadUser(k)); // atomic
cache.compute(key, (k, v) -> v == null ? new User() : v.withUpdatedAt(now())); // atomic update
// CopyOnWriteArrayList — fast reads, slow writes, iteration never throws CME
List<EventListener> listeners = new CopyOnWriteArrayList<>();
// BlockingQueue for producer-consumer
BlockingQueue<Task> queue = new LinkedBlockingQueue<>(1000);
queue.put(task); // blocks if full
queue.poll(1, TimeUnit.SECONDS); // waits up to 1s
```
## Key Rules
- Prefer virtual threads (Java 21) for I/O-bound work — they make blocking code cheap; no need for reactive frameworks for most use cases
- Never call `Future.get()` without a timeout — deadlocks are invisible without one
- `CallerRunsPolicy` is the simplest backpressure mechanism — caller slows down naturally
- `ConcurrentHashMap.computeIfAbsent` is atomic; `get` + `putIfAbsent` is not — always use the atomic compound operations
- Always release locks in `finally` — any exception before `unlock()` leaves the lock permanently held