学习并发先看这一介绍篇
先欣赏个美景~~
这我们前面说了Java的集合,接下来湿兄给大家肝个Java并发系列,这个系列多么重要不用我多说了吧,这篇是个大家先来个简单的汇总篇,为的是让大家学习之前多并发有个全局意识。
在写之前我也是读了很多并发多线程相关的书籍,加上我的工作中的实战经验,来给大家分享这部分相关知识,如果文章有错的地方还请大家多多包涵,不吝留言给湿兄指正,感谢~~
学习并发对于初学者来说大概需要两个阶段,第一个阶段是先学习基础篇的多线程知识,等对多线程的使用有了初步的使用和基本掌握之后。第二个阶段需要进入多线程进阶篇,进阶篇需要了解的是JUC并发包中各个多线程工具类之间的关系和使用。
如果你跟着湿兄读到了本系列的最后,也就是Executor框架那里,相信你会明白为什么我要强调这个全局意识的重要性。
并发这块的话,难点不在于多线程程序有多复杂,而在于理清JUC包中的各个多线程工具类的之间的关系,并不是说必须要弄懂源码,深入源码确实能够让你掌握底层原理,但是过分深入源码可能会导致“当局者迷”。大家要掌握好属于自己的学习方法哦~
推荐几本并发方面经典的书籍,《Java并发编程实战》、《Java并发编程的艺术》、《Java多线程编程核心技术》,这几本也是湿兄主要用来学习和复习的,可以读一波的哦~
认识多线程
提起线程,不得不提起的是进程,这两个经常被用来做对比
进程我们应该很了解,打开windows任务管理器,可以发现运行着很多后台进程:
进程的定义:
- 进程是系统进行资源分配和调度的基本单位,是操作系统的基础
- 进程是程序的实体,例如QQ、微信都对应着相应的进程
- 进程是一个具有独立功能的程序关于某个数据集合的一次运行活动
线程的定义:
- 线程是系统进行资源分配和调度的最小单位
- 被包含在进程中,是进程的实际运作单位,一个进程可以并发多个线程
进程和线程的区别:
- 进程是操作系统资源分配基本单位,线程是操作系统资源分配最小单位
- 一个进程可以包含多个线程,一个进程中的多个线程可以共同完成
- 进程有自己的独立运行空间,程序切换进程开销大;线程可以看做轻量级进程,每个线程有自己的运行栈和PC程序计数器,线程切换开销小
- 一个进程崩溃后,在保护模式下不会对其它进程产生影响,但是一个线程崩溃会导致整个进程崩溃掉,多进程比多线程健壮
为什么系统有了进程,已经可以进行资源分配和调度了,为什么还要线程?
- 进程开销大,引入更小消耗的线程能充分利用CPU,便于系统管理
- 多线程可以给用户带来更好的用户体验,程序有更好的并发性
举个进程和线程的例子吧,QQ运行着就是一个进程,而其中的聊天、查看空间啊等这些又是在不同的线程上来操作的~
认识JUC并发包
上面的线程学习了之后,接下来就要学习JUC包中各个多线程工具类之间的关系、特点和使用场景
JUC并发包,即java.util.concurrent包,是JDK自1.5之后引入的核心工具包,由著名并发大师Doug Lea实现
整个java.util.concurrent包可以大致按照如下划分:
- juc-locks锁框架
- juc-atomic原子类框架
- juc-sync同步类工具
- juc-collection同步集合类
- juc-executors执行器框架
我会按照上面的顺序来给大家分享相关的技术文章,给大家分享个不错的脑图
图片来源于https://mm.edrawsoft.cn/template/45972
juc-locks框架
在早期的JDK版本中,只提供了synchronized、wait、notify、notifyAll等比较底层的多线程同步工具,我们如果需要更复杂的多线程应用,一般需要基于JDK提供的这些基础工具进行自定义封装
JDK1.5之后,Doug Lea根据一些列常见的多线程设计模式,设计了这个JUC并发包提供了java.util.concurrent.locks这个包来对锁进行更多的补充和增强
java.util.concurrent.locks包的结构如下:
包内的接口和类的继承图:
了解即可,接下来我会通过更多的文章来介绍
juc-atomic原子类
我们在之前JDK版本若要并发的对Integer、Long、Double等这些Java原始类或引用类型来进行操作,一般需要我们通过锁来控制并发,以防数据不一致
在JDK1.5之后的并发包中的java.util.concurrent.atomic工具包,这个包提供了Java原始/引用类型的映射类,如AtomicInteger、AtomicLong、AtomicBoolean,这些类的底层是通过一种无锁算法来实现的
无锁算法:乐观锁机制,其实底层就是通过Unsafe类实现的一种比较并且交换的算法,大致的过程是,当希望修改的值与expectedValue相同时,则尝试将值更新为updateValue,更新成功返回true,否则返回false。
java.util.concurrent.atomic包结构如下:
包的接口和类的结构图:
juc-sync同步类框架
我们同步器框架,指的是java.util.concurrent下的一些辅助同步器类,这些类都有一些使用场景:
这几个工具类也是比较常用的,在面试中其实也是比较爱问的
juc-collection同步集合类
这是一些集合框架,是指的是java.util.concurrent包下的一些同步集合类,我们在线程安全的情况下经常会使用类似HashMap、ArrayList这些集合,这些集合都是线程不安全的,所以需要考虑使用环境
当多线程情况下,可以考虑使用这些同步集合类框架,按照类型划分为Map、List列表、Set集合、Queue队列四大类,每个类都有自己的使用场景
整个集合同步类架构图如下:
其中阻塞队列的分类及特性如下表:
juc-executors执行器框架
executors框架可以说是整个包中最复杂的一部分了,也是最需要了解深度的,executors其实可以划分为三块,但是每一块的核心都是基于Executor接口:
- 线程池
- Fork/Join框架
- Future模式
线程池是用于使用多线程的情况下,用于减小经常创建和销毁线程这些造成的资源消耗,线程池会提供一些活跃线程供用户随时取用;Fork/Join框架类似于Hadoop框架的一种思想,拆分处理再合并的思想;Future则是多线程中常用的一种异步执行任务的机制,并在需要的时候取得结果
絮叨叨
你知道的越多,你不知道的也越多。
建议:拒绝白嫖,关注湿兄,快乐和学习并发~
觉得不错的可以给大湿兄来个关注,也欢迎可爱帅气的你推荐给你的朋友,转发和点赞是可以给湿兄多打打气~~