Java 线程池实现原理及其在美团业务中的实践

随着计算机行业的飞速发展,摩尔定律逐渐失效,多核 CPU 成为主流。使用多线程并行计算逐渐成为开发人员提升服务器性能的基本武器。J.U.C 提供的线程池:ThreadPoolExecutor 类,帮助开发人员管理线程并方便地执行并行任务。了解并合理使用线程池,是一个开发人员必修的基本功。

本文开篇简述线程池概念和用途,接着结合线程池的源码,帮助读者领略线程池的设计思路,最后回归实践,通过案例讲述使用线程池遇到的问题,并给出了一种动态化线程池解决方案。

不可不说的 Java “锁”事

一、前言

Java 提供了种类丰富的锁,每种锁因其特性的不同,在适当的场景下能够展现出非常高的效率。本文旨在对锁相关源码(本文中的源码来自 JDK 8和 Netty 3.10.6)和使用场景进行举例,为读者介绍主流锁的知识点,以及不同的锁的适用场景。

Java 中往往是按照是否含有某一特性来定义锁,我们通过特性将锁进行分组归类,再使用对比的方式进行介绍,帮助大家更快捷的理解相关知识。下面给出本文内容的总体分类目录:

Java 并发编程——线程池的异常处理机制

一、前言

1.1 文章起因

这篇文章的起因来源于一个 BUG,这个 BUG 和上篇文章《Java SynchronizedSet 线程不安全之坑》 有点关系。简单来说,就是在线程池中执行任务,任务本身未做异常处理,导致出现异常后任务停止。

出错的原因来自对 Collections.synchronizedSet(new HashSet<>()) 的线程不安全访问,抛出了 ConcurrentModificationException

问题的关键是在事后查询线上日志时并没有发现相关异常记录,导致问题的排查变得困难。所幸最后找到了问题,同时也发现了默认情况下线程中的异常是不会被记录到日志中的,也算是踩了个坑吧,这就是这篇文章的由来。

Java SynchronizedSet 线程不安全之坑

一、前言

一般而言,想要构造出线程安全的 Set,我们会使用 Collections.synchronizedSet 方法,如下所示。

Set<User> set = Collections.synchronizedSet(new HashSet<>());

但这并不意味着,你可以安全的使用该集合的任何方法,如果没有仔细的了解过其实现的话,一不小心就会踩进坑中。最近我在使用该集合的 stream 方法时发现了线程不安全问题,都是血的教训啊,下面写个Case 来复现下吧。

为什么阿里巴巴要禁用 Executors 创建线程池?

一、写在前面

通过阅读本篇文章你将了解到:

  • 线程池的定义
  • Executors 创建线程池的几种方式
  • ThreadPoolExecutor 对象
  • 线程池执行任务逻辑和线程池参数的关系
  • Executors 创建返回 ThreadPoolExecutor 对象
  • OOM 异常测试
  • 如何定义线程池参数

Java-并发编程——CyclicBarrier

一、简介

CyclicBarrier 是一个同步工具类,它允许一组线程在到达某个栅栏点(common barrier point)互相等待,发生阻塞,直到最后一个线程到达栅栏点,栅栏才会打开,处于阻塞状态的线程恢复继续执行.它非常适用于一组线程之间必需经常互相等待的情况。CyclicBarrier 字面理解是循环的栅栏,之所以称之为循环的是因为在等待线程释放后,该栅栏还可以复用。

Java 并发编程——LinkedBlockingQueue

在集合框架里,ArrayList 和 LinkedList 是使用最多的两种集合。ArrayList 和 ArrayBlockingQueue 一样,内部基于数组来存放元素,而 LinkedBlockingQueue 则和 LinkedList 一样,内部基于链表来存放元素。

LinkedBlockingQueue 实现了 BlockingQueue 接口,不同于 ArrayBlockingQueue,它如果不指定容量,容量默认为 Integer.MAX_VALUE,也就是无界队列

Java 并发编程——ArrayBlockingQueue

一、简介

ArrayBlockingQueue 顾名思义:基于数组的阻塞队列。数组是要指定长度的,所以使用 ArrayBlockingQueue 时必须指定长度,也就是它是一个有界队列。它实现了 BlockingQueue 接口,有着队列、集合以及阻塞队列的所有方法。