线程池优化:合理配置核心参数
在Java多线程开发中,线程池是最关键的组件之一。通过ThreadPoolExecutor的合理配置,可以显著提升系统吞吐量。核心线程数(corePoolSize)应该设置为CPU核心数的1-1.5倍,最大线程数(maximumPoolSize)则需要根据任务类型调整:CPU密集型任务建议设置为CPU核心数+1,而IO密集型任务可以设置为2*CPU核心数。
工作队列的选择同样重要:LinkedBlockingQueue适合平稳流量场景,而SynchronousQueue则适用于突发流量。对于拒绝策略,CallerRunsPolicy可以在线程池饱和时让调用线程执行任务,避免任务丢失。
并发容器替代同步集合
Java并发包(java.util.concurrent)提供了高性能的并发容器,比传统的同步集合(Synchronized Collections)效率更高。ConcurrentHashMap采用分段锁技术,在读多写少场景下性能是Hashtable的数十倍。CopyOnWriteArrayList适合读多写少的列表场景,通过写时复制机制保证线程安全。
BlockingQueue系列是生产者-消费者模式的绝佳实现,ArrayBlockingQueue适合固定大小队列,而LinkedBlockingQueue则更适合无界队列场景。这些并发容器内部都采用了精妙的锁优化技术,如自旋锁、CAS操作等。
CompletableFuture实现异步编排
Java8引入的CompletableFuture为复杂的异步编程提供了优雅的解决方案。通过thenApply、thenAccept等方法链式调用,可以构建清晰的异步处理流程。异常处理通过exceptionally方法实现,比传统的Future.get()更加灵活。
组合多个CompletableFuture时,allOf和anyOf方法非常实用。例如电商系统中,可以并行查询商品信息、库存和评价,最后统一组装返回结果。这种模式比串行调用效率提升显著,特别是在微服务架构中。
锁优化技巧与注意事项
锁竞争是多线程性能的主要瓶颈之一。首先考虑使用synchronized的代码块而非方法,减小锁粒度。读写锁(ReentrantReadWriteLock)在读多写少场景下比互斥锁效率更高。
JDK提供的StampedLock是更先进的锁实现,特别是乐观读模式可以进一步提升性能。对于计数器等场景,Atomic原子类比锁效率更高。要注意避免死锁,按固定顺序获取多个锁,并设置合理的超时时间。
ThreadLocal的正确使用与内存泄漏防范
ThreadLocal是线程封闭技术的典型实现,适合存储线程上下文信息。但使用不当会导致内存泄漏,因为ThreadLocalMap的Entry是弱引用,但value是强引用。
正确的做法是:1)使用static final修饰ThreadLocal实例;2)在finally块中调用remove()方法清理;3)考虑使用 InheritableThreadLocal 时需要特别小心。在Web应用中,Filter是清理ThreadLocal的理想位置。