在微服务架构下,多线程编程已经成为Java开发者的必备技能。本文将帮助你掌握多线程开发的核心知识,避开常见陷阱。
// ❌ 错误示例:直接使用Executors创建线程池
ExecutorService executor = Executors.newFixedThreadPool(10);
// ❌ 错误示例:没有明确的拒绝策略
ThreadPoolExecutor executor = new ThreadPoolExecutor(
10, 10, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>()
);
// ✅ 推荐示例:自定义线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5, // 核心线程数
10, // 最大线程数
60L, // 空闲线程存活时间
TimeUnit.SECONDS, // 时间单位
new LinkedBlockingQueue<>(100), // 有界队列
new ThreadFactoryBuilder()
.setNameFormat("业务名称-thread-%d")
.build(), // 自定义线程工厂
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
);
// 优雅关闭线程池
void shutdownThreadPool(ThreadPoolExecutor executor) {
executor.shutdown();
try {
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
}
}
// ❌ 错误示例:在并发环境下使用HashMap
Map<String, Object> map = new HashMap<>();
// ✅ 推荐示例1:ConcurrentHashMap(推荐)
Map<String, Object> map = new ConcurrentHashMap<>();
// ✅ 推荐示例2:需要独占锁时使用Collections.synchronizedMap
Map<String, Object> map = Collections.synchronizedMap(new HashMap<>());
// ❌ 错误示例:ArrayList非线程安全
List<String> list = new ArrayList<>();
// ✅ 推荐示例1:写多读少场景
List<String> list = new CopyOnWriteArrayList<>();
// ✅ 推荐示例2:读多写少场景
List<String> list = Collections.synchronizedList(new ArrayList<>());
// ❌ 错误示例:容易造成死锁
synchronized void transfer(Account from, Account to, double amount) {
synchronized(from) {
synchronized(to) {
// 转账逻辑
}
}
}
// ✅ 推荐示例:按固定顺序获取锁
synchronized void transfer(Account from, Account to, double amount) {
Account first = from.getId() < to.getId() ? from : to;
Account second = from.getId() < to.getId() ? to : from;
synchronized(first) {
synchronized(second) {
// 转账逻辑
}
}
}
// ✅ 推荐示例1:细粒度锁
public class UserService {
private final Map<Long, Lock> lockMap = new ConcurrentHashMap<>();
public void updateUser(Long userId) {
Lock lock = lockMap.computeIfAbsent(userId, k -> new ReentrantLock());
lock.lock();
try {
// 更新用户逻辑
} finally {
lock.unlock();
}
}
}
// ✅ 推荐示例2:读写锁
public class CacheService {
private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
private final Map<String, Object> cache = new HashMap<>();
public Object read(String key) {
rwLock.readLock().lock();
try {
return cache.get(key);
} finally {
rwLock.readLock().unlock();
}
}
public void write(String key, Object value) {
rwLock.writeLock().lock();
try {
cache.put(key, value);
} finally {
rwLock.writeLock().unlock();
}
}
}
public class ConcurrentCache<K, V> {
private final ConcurrentHashMap<K, V> cache = new ConcurrentHashMap<>();
private final LoadingCache<K, V> guavaCache;
public ConcurrentCache(CacheLoader<K, V> loader) {
this.guavaCache = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build(loader);
}
public V get(K key) {
V value = cache.get(key);
if (value == null) {
// 双重检查锁定
synchronized(cache) {
value = cache.get(key);
if (value == null) {
value = guavaCache.getUnchecked(key);
cache.put(key, value);
}
}
}
return value;
}
}
// ❌ 错误示例:方法级同步
public synchronized void process(List<Order> orders) {
orders.forEach(this::processOrder);
}
// ✅ 推荐示例:缩小同步范围
public void process(List<Order> orders) {
orders.parallelStream()
.forEach(order -> {
synchronized(order) {
processOrder(order);
}
});
}
// ✅ 推荐示例:状态标志
public class TaskManager {
private volatile boolean running = true;
public void shutdown() {
running = false;
}
public void process() {
while (running) {
// 处理任务
}
}
}
CPU飙升
内存泄漏
响应超时
// 线程池监控
public class MonitoredThreadPool extends ThreadPoolExecutor {
private final AtomicLong totalTasks = new AtomicLong(0);
private final AtomicLong completedTasks = new AtomicLong(0);
@Override
protected void beforeExecute(Thread t, Runnable r) {
totalTasks.incrementAndGet();
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
completedTasks.incrementAndGet();
// 记录监控指标
if (t != null) {
log.error("Task execution failed", t);
}
}
}
多线程开发要点:
建议: