VJTools项目中的并发处理最佳实践指南

VJTools项目中的并发处理最佳实践指南

vjtools The vip.com's java coding standard, libraries and tools vjtools 项目地址: https://gitcode.com/gh_mirrors/vj/vjtools

前言

并发编程是Java开发中非常重要的一个领域,也是容易出现问题的重灾区。VJTools项目总结了一套关于并发处理的规范和实践经验,本文将对这些内容进行系统梳理和扩展讲解,帮助开发者更好地理解和应用这些并发编程的最佳实践。

一、线程创建与管理规范

1.1 线程命名的重要性

在创建线程或线程池时,必须为线程指定有意义的名称。这不仅仅是规范问题,更是线上问题排查的重要依据。

正确做法:

  • 单线程直接设置名称
  • 线程池使用ThreadFactory指定命名规则
// 单线程命名
Thread t = new Thread();
t.setName("order-process-thread");

// 线程池命名
ThreadFactory threadFactory = new ThreadFactoryBuilder()
    .setNameFormat("payment-pool-%d").build();

1.2 优先使用线程池

直接创建线程会导致资源管理失控,应该始终优先使用线程池:

// 错误示范
new Thread(task).start();

// 正确做法
ExecutorService executor = Executors.newFixedThreadPool(10);
executor.execute(task);

对于定时任务,也应该使用ScheduledExecutorService而非Timer类,因为Timer存在单线程执行和异常传播的问题。

二、线程池的正确使用

2.1 避免使用Executors创建线程池

Executors工具类虽然方便,但隐藏了资源耗尽的风险:

| 线程池类型 | 问题 | |------------|------| | FixedThreadPool/SingleThreadPool | 无界队列可能导致OOM | | CachedThreadPool/ScheduledThreadPool | 无界线程数可能导致OOM |

推荐做法:

new ThreadPoolExecutor(
    corePoolSize,
    maxPoolSize,
    keepAliveTime,
    TimeUnit.SECONDS,
    new ArrayBlockingQueue<>(queueSize),
    threadFactory,
    new ThreadPoolExecutor.AbortPolicy()
);

2.2 优雅停止线程池

正确的线程池关闭流程:

  1. 先调用shutdown()拒绝新任务
  2. 再调用shutdownNow()中断正在执行的任务
  3. 可配合awaitTermination()等待任务结束

三、线程安全编程实践

3.1 正确处理线程中断

实现可中断的Runnable需要注意:

  1. 在可能阻塞的操作前检查中断状态
  2. 正确处理InterruptedException
  3. 不要吞掉中断异常

错误示例:

public void run() {
    while(true) {  // 未检查中断状态
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            logger.warn("Interrupted", e); // 吞掉异常
        }
    }
}

正确实现:

public void run() {
    try {
        while (!Thread.interrupted()) {
            // 业务逻辑
        }
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt(); // 恢复中断状态
    }
}

3.2 捕获所有运行时异常

未捕获的异常会导致:

  • 定时任务中断执行
  • 线程池线程终止
  • 日志丢失(仅打印到System.err)

解决方案:

executor.execute(() -> {
    try {
        // 业务代码
    } catch (Exception e) {
        logger.error("Task failed", e);
    }
});

四、并发工具与模式

4.1 ThreadLocal的正确使用

对于非线程安全的类(如SimpleDateFormat),可以使用ThreadLocal:

private static final ThreadLocal<SimpleDateFormat> DATE_FORMAT = 
    ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));

public String formatDate(Date date) {
    return DATE_FORMAT.get().format(date);
}

注意每次使用前可能需要重置状态(如MessageDigest)。

4.2 锁优化技巧

  1. 锁粒度:尽量缩小锁范围
  2. 锁类型:优先使用对象锁而非类锁
  3. 锁分离:读写锁、分段锁等
  4. 无锁结构:Atomic类、ConcurrentHashMap等

4.3 volatile与原子类

  • volatile解决可见性问题
  • 原子类解决复合操作的原子性问题
// 可见性
private volatile boolean running = true;

// 原子操作
private AtomicInteger counter = new AtomicInteger();
counter.incrementAndGet();

五、高级并发模式

5.1 延迟初始化方案

不推荐使用双重检查锁,推荐静态内部类方式:

public class Singleton {
    private static class Holder {
        static final Singleton INSTANCE = new Singleton();
    }
    
    public static Singleton getInstance() {
        return Holder.INSTANCE;
    }
}

5.2 避免死锁

  1. 保持加锁顺序一致
  2. 使用tryLock带超时机制
  3. 避免嵌套锁

总结

VJTools项目中总结的这些并发处理规范,涵盖了从线程创建、线程池使用到高级并发模式等多个方面。遵循这些最佳实践可以帮助开发者:

  1. 编写更安全的并发代码
  2. 避免常见的并发陷阱
  3. 提高系统稳定性和性能
  4. 便于问题排查和诊断

在实际开发中,应当根据具体场景选择合适的并发策略,并在性能与安全性之间取得平衡。

vjtools The vip.com's java coding standard, libraries and tools vjtools 项目地址: https://gitcode.com/gh_mirrors/vj/vjtools

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凤红令Nathania

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值