前言

发现自己一直没有系统地学习 JUC。这篇博客仅作为学习过程中的记录所用。

JUC 指的是 java.util.concurrent。此包的出现是为了更好的支持多线程、高并发任务。

线程基础

线程有六个状态:NEWRUNNABLEBLOCKEDWAITINGTIMED_WATTINGTERMINATED

JUC 的结构

JUC 包含以下内容:Synchronization Utilities(同步工具),Thread Pools(线程池),Concurrent Collections(并发集合),Locks(锁),Atomic Variables(原子变量)。

Synchronization Utilities

即同步工具类。包含:CountDownLatch(闭锁)、CyclicBarrier(栅栏)、Semaphore(信号量)、Exchanger(交换者)。

CountDownLatch

CountDownLatch 定义了一个计数器和一个阻塞队列。 当计数器的值递减为 0 之前,阻塞队列里面的线程处于挂起状态,当计数器递减到 0 时会唤醒阻塞队列所有线程。

CyclicBarrier

CyclicBarrier 允许一组线程互相等待,直到所有线程都到达一个共同的屏障点,然后所有线程才能继续执行。与 CountDownLatch 不同的是,CyclicBarrier 可以被重置并重复使用。

Semaphore

Semaphore 维护了一组 permits,线程在进入临界区之前必须从 Semaphore 获取 permits,当退出临界区时释放 permitspermits 的数量决定了可以同时访问资源的线程数。Semaphore 既可以作为互斥锁(类似 ReentrantLock),也可以用于限制并发量。

Exchanger

Exchanger 提供了一个同步点,两个线程在这个同步点上交换数据。当一个线程调用 exchange 方法时,它会进入等待状态,直到另一个线程也调用 exchange 方法。然后两个线程交换数据并继续执行。

Thread Pools

用于管理和复用一组线程,以执行异步任务。线程池通过预先创建一定数量的线程并将其保存在池中,任务提交时,线程池会将任务分配给池中的线程执行。任务完成后,线程不会被销毁,而是返回到池中,等待下一个任务。

常见的线程池类型:FixedThreadPoolCachedThreadPoolSingleThreadExecutorScheduledThreadPoolWorkStealingPool

FixedThreadPool

创建一个固定大小的线程池,线程数量是固定的。

当任务被提交时,如果有空闲线程,任务会立即执行。如果没有空闲线程,任务会被放入一个等待队列中,等待线程空闲时执行。线程池中的线程数量是固定的,不会因为任务的增加而增加,也不会因为任务的减少而减少。

CachedThreadPool

适用于需要执行大量短期异步任务的场景。

当任务被提交时,如果有空闲线程,任务会立即执行。如果没有空闲线程,线程池会创建新线程来处理任务。线程空闲时会被保留一段时间(默认 60 秒),如果在这段时间内没有新任务,它们会被终止并从池中移除。

SingleThreadExecutor

创建一个单线程执行器,以确保所有任务按顺序在同一个线程中执行。

SingleThreadExecutor 内部维护一个单一的工作线程。当任务被提交时,如果工作线程空闲,任务会立即执行。如果工作线程正在执行任务,新提交的任务会被放入一个等待队列中,按照提交顺序依次执行。即使在出现异常时,线程池也会保证顺序执行下一个任务。

ScheduledThreadPool

允许任务在预定的延迟后执行,也可以按照固定的频率重复执行。

ScheduledThreadPool 内部维护一个线程池和一个任务队列。可以使用 schedule 方法提交延迟执行的任务,或使用 scheduleAtFixedRatescheduleWithFixedDelay 方法提交周期性执行的任务。schedule 方法允许任务在指定的延迟时间后执行一次。scheduleAtFixedRate 方法允许任务以固定的频率重复执行,无论任务执行时间长短。scheduleWithFixedDelay 方法允许任务在前一个任务完成后,经过固定的延迟时间后再执行。

WorkStealingPool

使用工作窃取(work stealing)算法来提高并行任务的执行效率。

WorkStealingPool 内部维护了一个线程池,每个线程都有自己的工作队列。当一个线程完成了自己的任务后,它会去其他线程的工作队列中偷取任务来执行,这样可以有效地避免线程空闲。工作窃取算法使得任务的执行更加高效,特别适用于处理递归式、可分解的任务。

Concurrent Collections

并发集合是一组线程安全的集合类,用于在多线程环境下进行数据共享和并发访问。这些集合类提供了高效的并发访问机制,可以在不需要显式同步的情况下安全地在多个线程之间共享数据。

常见的并发集合类:ConcurrentHashMapConcurrentSkipListMapConcurrentSkipListSetConcurrentSkipListSetCopyOnWriteArraySetConcurrentLinkedQueueConcurrentLinkedDeque 等。

ConcurrentHashMap

HashMap 的线程安全版本。其不允许键或值为 null。提供了线程安全的迭代器。

ConcurrentHashMap 使用分段锁算法,提高并发性能。

ConcurrentSkipListMap

是一种随机化的数据结构,通过跳表实现。

ConcurrentSkipListMapkey 是有序的,支持更高的并发。