Java并发编程汇总
2026-02-02 18:53:25 0 举报
AI智能生成
Java并发编程核心内容涵盖了线程的创建、管理和同步,包含了线程的基本概念、线程池的使用、并发工具类(如CountDownLatch、CyclicBarrier、Semaphore、Exchanger等)、同步机制(如synchronized关键字、Lock接口及其实现类如ReentrantLock)、原子操作类、线程安全集合类等。这些内容不仅能帮助开发者构建高效、安全的多线程程序,还能让程序具有更好的性能和可伸缩性。文件类型可能为.pdf、.docx或.html格式,具体取决于存放平台和个人偏好。修饰语可能包括“权威指南”、“核心教程”、“实战演练”等,用以强调内容的专业性和实践价值。在描述这些内容时,需要遵循准确、简洁、易懂的原则。
作者其他创作
大纲/内容
一、线程基础概念
基础概念
进程与线程的区别
进程:Process,(正在执行中的程序)是一个静态的概念
1.进程是程序的一次静态态执行过程, 占用特定的地址空间.<br>2.每个进程都是独立的,由3部分组成cpu,data,code<br>3.缺点:内存的浪费,cpu的负担
线程:是进程中一个“单一的连续控制流程” (a single<br>sThread,equential flow of control)/执行路径
1.线程又被称为轻量级进程(lightweight process)。<br>2.Threads run at the same time, independently of one another<br>3.一个进程可拥有多个并行的(concurrent)线程<br>4.一个进程中的线程共享相同的内存单元/内存地址空间可以访问相同的<br>变量和对象,而且它们从同一堆中分配对象通信、数据交换、同步操作<br>5.由于线程间的通信是在同一地址空间上进行的,所以不需要额外的通信<br>机制,这就使得通信更简便而且信息传递的速度也更快。
CPU与线程的关系
什么是多线程
多线程是指:单个进程中同时运行多个线程。<br><br>多线程的目的是为了提高CPU的利用率。<br>可以通过避免一些网络IO或者磁盘IO等需要等待的操作,让CPU去调度其他线程。<br>这样可以大幅度的提升程序的效率,提高用户的体验。<br><br>比如Tomcat可以做并行处理,提升处理的效率,而不是一个一个排队。<br>不如要处理一个网络等待的操作,开启一个线程去处理需要网络等待的任务,<br>让当前业务线程可以继续往下执行逻辑,效率是可以得到大幅度提升的。
多线程的局限
如果线程数量特别多,CPU在切换线程上下文时,会额外造成很大的消耗。<br><br>任务的拆分需要依赖业务场景,有一些异构化的任务,很难对任务拆分,还有很多业务并不是多线程处理更好。<br>
线程安全问题
虽然多线程带来了一定的性能提升,但是再做一些操作时,多线程如果操作临界资源,<br>可能会发生一些数据不一致的安全问题,甚至涉及到锁操作时,会造成死锁问题。
并行与并发的区别
串行
串行就是一个一个排队,第一个做完,第二个才能上
并行
并行就是同时处理。(一起上!!!)
并发
这里的并发并不是三高中的高并发问题,这里是多线程中的并发概念(CPU调度线程的概念)。<br>CPU在极短的时间内,反复切换执行不同的线程,看似好像是并行,但是只是CPU高速的切换。<br>并行囊括并发。<br>并行就是多核CPU同时调度多个线程,是真正的多个线程同时执行。<br>单核CPU无法实现并行效果,单核CPU是并发。
线程的创建
继承Thread类 重写run方法
▪ 在Java中负责线程的这个功能的是Java.lang.Thread 这个类<br>▪ 可以通过创建 Thread 的实例来创建新的线程。<br>▪ 每个线程都是通过某个特定Thread对象所对应的方法run( )来完<br>成其操作的,方法run( )称为线程体。<br>▪ 通过调用Thead类的start()方法来启动一个线程。
操作步骤
【1】继承Thread类<br>【2】重写run方法<br>【3】创建对象, 调用start()方法, 启动线程<br>
线程的执行
不要直接调用run方法,而需要使用Thread类的start方法才能够启动线程,直接调用run相当于就是一次普通的方法调用
实现Runnable接口 重写run方法
操作步骤
【1】实现Runnable接口<br>【2】重写run方法<br>【3】创建Thread对象,将刚刚创建好的runnable的子类实例作为thread的构造参数<br>【4】调用thread.start()方法, 启动线程<br>
该实现方式使用了<b><font color="#e74f4c">代理设计模式</font></b>
实现Callable接口 重写call方法,配合FutureTask
【1】实现Callable接口<br>【2】重写call方法<br>【3】创建FutureTask,传入Callable实现类的实例<br>【4】创建Thread对象,将刚刚创建好的FutureTask的实例作为thread的构造参数<br>【5】调用thread.start()方法, 启动线程
三种方式的详细对比
核心区别分析
1. 继承关系与代码结构
2. 资源共享能力
3. 返回值与异常处理
如何选择实现方式?
选择继承Thread类的情况
简单测试场景:快速创建线程进行测试<br>不需要资源共享:每个线程完全独立<br>不需要继承其他类:不会与现有继承结构冲突<br>线程专用功能:需要重写Thread类的方法
选择实现Runnable接口的情况(<b>推荐首选</b>)
需要资源共享:多个线程处理同一资源<br>已有继承结构:类已经继承其他父类<br>线程池任务:需要提交任务到线程池<br>代码复用:同一个任务对象可被多个线程执行<br>函数式编程:可与lambda表达式结合
选择实现Callable接口的情况
需要返回值:线程执行后需要返回结果<br>需要异常处理:任务可能抛出受检异常<br>异步计算结果:配合Future获取异步结果<br>并行计算任务:多个任务并行执行并汇总结果<br>超时控制:Future支持get(timeout, unit)
最佳实践建议
线程的基本使用
线程的状态
5种状态一般是针对传统的线程状态来说(操作系统层面)
Java中给线程准备的6种状态
<br>
NEW:Thread对象被创建出来了,但是还没有执行start方法。
RUNNABLE:Thread对象调用了start方法,就为RUNNABLE状态(CPU调度/没有调度)
BLOCKED:synchronized没有拿到同步锁,被阻塞的情况
WAITING:调用wait方法就会处于WAITING状态,需要被手动唤醒
TIME_WAITING:调用sleep方法或者join方法,会被自动唤醒,无需手动唤醒
TERMINATED:run方法执行完毕,线程生命周期到头了
线程的启动
start和run的区别
不要直接调用run方法,而需要使用Thread类的start方法才能够启动线程,直接调用run相当于就是一次普通的方法调用
线程的常用方法
获取当前线程-Thread.currentThread
线程的名字-name
线程的优先级-priority
线程的让步-yield
线程的休眠-sleep
线程的强占-join
守护线程-daemon
线程的终止方式
自然结束(能自然结束就尽量自然结束)
stop方式结束(不用)
共享变量结束线程(很少会用)
中断标记位-interrupt方法
通过打断WAITING或者TIMED_WAITING状态的线程,从而抛出异常自行处理
锁的基本概念
synchronized基本使用
对象锁
类锁
线程的等待与唤醒
线程的等待-wait
可以让获取synchronized锁资源的线程通过wait方法进去到锁的<b>等待池</b>,并且会释放锁资源
wait和sleep的区别
join与sleep的区别
核心区别对比
详细工作原理
使用示例与对比
实际应用场景
注意事项与最佳实践
总结与选择建议
线程的唤醒-notify,notifyAll
可以让获取synchronized锁资源的线程,通过notify或者notifyAll方法,将等待池中的线程唤醒,添加到<b>锁池</b>中
二、并发编程的三大特性
可见性
CPU的可见性
什么是并发编程的可见性
解决可见性的方式
volatile
synchronized
lock
final
MESI协议
@Contended
原子性
CPU的原子性
什么是并发编程的原子性
i++分析
如何保证原子性
synchronized
Lock锁
ReentrantLock的基本使用
CAS
CAS的基本使用
CAS原理
CAS的三个问题
ThreadLocal
ThreadLocal基本使用
ThreadLocal原理
ThreadLocal的内存泄漏问题
有序性
CPU的有序性
什么是并发编程的有序性
如何保证有序性
as-if-serial
happens-before
volatile
JMM-Java内存模型
三、锁
锁的分类
可重入锁、不可重入锁
乐观锁、悲观锁
公平锁、非公平锁
互斥锁、共享锁
深入synchronized
synchronized基本使用
对象锁
如果使用非static同步方法:此时使用的是当前对象做为锁(对象锁)
类锁
如果使用static同步方法:此时使用的是当前类.class作为锁(类锁)
synchronized的优化
锁消除
锁膨胀
锁升级
synchronized实现原理
synchronized的锁升级
synchronized的特性
synchronized的底层
加锁流程
1 分析enter函数
2 分析EnterI函数
3 分析tryLock&trySpin函数
释放锁流程
深入ReentrantLock
ReentrantLock和synchronized的区别
AQS概述
浅聊ReentrantLock
AQS中常见的问题
ReentrantLock详细底层
加锁流程
这里咱们以非公平锁的方式,去看lock方法加锁的过程。
加锁流程源码剖析
加锁流程概述
三种加锁源码分析
lock方法源码分析
tryLock方法源码分析
lockInterruptibly方法源码分析
释放锁流程
<br>
释放锁流程源码剖析
释放锁流程概述
释放锁源码分析
<br>
ConditionObject
1.ConditionObject的介绍&应用
2.Condition的构建方式&核心属性
3.Condition的await方法分析(前置分析)
4.Condition的signal方法分析
5.Conditiond的await方法分析(后置分析)
6.Condition的awaitNanos&signalAll方法分析
深入ReentrantReadWriteLock
读写锁概述
写锁分析
写锁加锁流程概述
写锁加锁流程源码剖析
lock源码分析
lockInterruptibly源码分析
tryLock()&tryLock(timeout, unit)源码分析
写锁释放锁流程源码剖析
写锁流程概述
unlock源码分析
读锁分析
读锁加锁流程概述
读锁加锁流程源码剖析
lock源码分析
lockInterruptibly源码分析
tryLock()&tryLock(timeout, unit)源码分析
读锁释放锁流程源码剖析
读锁流程概述
unlock源码分析
ReentrantReadWriteLock的设计思想
四、阻塞队列
生产者消费者概念
JUC阻塞队列的存取方法
生产者存储方法
消费者取数据方法
ArrayBlockingQueue应用&源码分析
用数组实现的有界阻塞队列
ArrayBlockingQueue的基本使用
生产者方法实现原理
消费者方法实现原理
LinkedBlockingQueue应用&源码分析
用链表实现的有界阻塞队列
LinkedBlockingQueue的底层实现
生产者方法实现原理
消费者方法实现原理
PriorityBlockingQueue应用&源码分析
支持优先级的无界阻塞队列
二叉堆结构介绍
PriorityBlockingQueue核心属性
PriorityBlockingQueue的写入操作
PriorityBlockingQueue的读取操作
DelayQueue应用&源码分析
支持延时获取元素的无界阻塞队列
DelayQueue核心属性
DelayQueue写入流程分析
DelayQueue读取流程分析
SynchronousQueue应用&源码分析
不存储元素的阻塞队列
SynchronousQueue核心属性
SynchronousQueue的TransferQueue源码
tansfer方法流程图
八、异步编程
FutureTask应用&源码分析
FutureTask介绍
FutureTask应用
FutureTask源码分析
FutureTask中的核心属性
FutureTask的run方法
FutureTask的set&setException方法
FutureTask的cancel方法
FutureTask的get方法
FutureTask的finishCompletion方法
CompletableFuture应用&源码分析
CompletableFuture介绍
CompletableFuture应用
supplyAsync
runAsync
thenApply,thenApplyAsync
thenAccept,thenAcceptAsync
thenRun,thenRunAsync
thenCombine,thenAcceptBoth,runAfterBoth
applyToEither,acceptEither,runAfterEither
exceptionally,whenComplete,handle
allOf,anyOf
CompletableFuture核心源码流程分析
当前任务执行方式
任务编排的存储&执行方式
任务编排流程
查看后置任务执行时机
CompletableFuture执行流程图
七、JUC并发工具
CountDownLatch应用&源码分析
CountDownLatch介绍
CountDownLatch应用
CountDownLatch源码分析
有参构造
await方法
countDown方法
CyclicBarrier应用&源码分析
CyclicBarrier介绍
CyclicBarrier应用
CyclicBarrier源码分析
CyclicBarrier的核心属性
CyclicBarrier的有参构造
CyclicBarrier中的await方法
Semaphore应用&源码分析
Semaphore介绍
Semaphore应用
Semaphore源码分析
Semaphore的整体结构
Semaphore的非公平的获取资源
Semaphore公平实现
Semaphore释放资源
AQS中PROPAGATE节点
掌握JDK1.5-Semaphore执行流程图
分析JDK1.8的变化
六、并发集合
CHM宏观写入数据流程
CHM宏观扩容流程&协助扩容
CHM宏观查询数据流程
ConcurrentHashMap源码分析(JDK1.8)
存储结构
存储操作
扩容操作
红黑树操作
查询数据
ConcurrentHashMap其他方法
compute方法
replace方法详解
merge方法详解
ConcurrentHashMap计数器
addCount方法分析
size方法方法分析
JDK1.7的HashMap的环形链表
CopyOnWriteArrayList
CopyOnWriteArrayList介绍
核心属性&方法
读操作
写操作
移除数据
覆盖数据&清空集合
迭代器
五、线程池
什么是线程池
线程池体系结构
<b>Executor:</b>线程池顶级接口<br>
<b>ExecutorService:<br></b>线程池次级接口,继承自Executor,<br>对Executor做了一些扩展,增加了一些功能<br>
<b>ScheduledExecutorService:<br></b>继承自ExecutorService,对ExecutorService做了一些扩展,增加一些定时任务相关的功能<br>
<b>ScheduledThreadPoolExecutor:<br></b>定时任务线程池类,用于实现定时任务相关功能,实现了ScheduledExecutorService
newSingleThreadScheduledExecutor
newScheduledThreadPool
<b>AbstractExecutorService:<br></b>抽象类,运用模板方法设计模式实现了一部分方法,实现了ExecutorService
<b>ThreadPoolExcutor:<br></b>普通线程池类,包含最基本的一些线程池操作相关的方法实现
newFixedThreadPool
newCachedThreadPool
newSingleThreadPool
<b>ForkJoinPool:<br></b>新型线程池类,JAVA7中新增的线程池类,<br>基于工作窃取理论实现,运用于大任务拆小任务,任务无限多的场景
newWorkStealingPool
ThreadPoolExecutor应用&源码剖析
为什么要自定义线程池
ThreadPoolExecutor应用
ThreadPoolExecutor的核心参数
参数列表
corePoolSize:核心线程数
maximumPoolSize:线程池能创建线程的最大个数
keepAliveTime:空闲线程存活时间
unit:时间单位,为keepAliveTime指定时间单位
workQueue:阻塞队列,用于保存任务的阻塞队列
BlockingQueue
ArrayBlockingQueue
Linked<span style="font-size:inherit;">BlockingQueue</span>
DelayQueue
PriorityBlockingQueue
SynchronousQueue
threadFactory:创建线程的工程类
handler:饱和策略(拒绝策略)
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出<br>RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛<br>出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的<br>任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
ThreadPoolExecutor的状态
线程池的生命周期
running
能接受新提交的任务,并且也能处理阻塞队列中的任务
shutdown
关闭状态,不再接受新提交的任务,但却可以继续处理阻<br>塞队列中已保存的任务
stop
不能接受新任务,也不处理队列中的任务,会中断正在处理任务的<br>线程。
tidying
如果所有的任务都已终止了,workerCount (有效线程数) 为0,<br>线程池进入该状态后会调用 terminated() 方法进入TERMINATED 状态
terminated
在terminated() 方法执行完后进入该状态,默认<br>terminated()方法中什么也没有做
ThreadPoolExecutor源码剖析
ThreadPoolExecutor的核心属性
ThreadPoolExecutor的有参构造
ThreadPoolExecutor的execute方法
execute方法的完整执行流程图
executor方法的执行逻辑
如果当前运行的线程少于corePoolSize,则会创建新的线程来执行新的任务;
如果运行的线程个数等于或者大于corePoolSize,则会将提交的<br>任务存放到阻塞队列workQueue中;
如果当前workQueue队列已满的话,则会创建新的线程来执行任务;
如果线程个数已经超过了maximumPoolSize,则会使用饱和策<br>略RejectedExecutionHandler来进行处理。
ThreadPoolExecutor的addWorker方法
ThreadPoolExecutor的Worker工作线程
ThreadPoolExecutor的runWorker方法
ThreadPoolExecutor的getTask方法
ThreadPoolExecutor的关闭方法
ThreadPoolExecutor拒绝策略
ThreadPoolExecutor核心线程数设计原则
线程池的核心参数设计规则
线程池处理任务的核心流程
基于addWorker添加工作线程的流程切入到整体处理任务的位置
ScheduledThreadPoolExecutor应用&源码剖析
ScheduleThreadPoolExecutor介绍
ScheduledThreadPoolExecutor应用
ScheduledThreadPoolExecutor源码剖析
ScheduledThreadPoolExecutor的实现原理
scheduleAtFixedRate和scheduleWithFixedDelay的区别
多线程场景应用实战
线程池 + ReentrantReadWriteLock项目落地
线程池 + FutureTask的实战应用
0 条评论
下一页