并发编程可以总结为3个核心问题:
JavaSDK并发包很大部分都是按照这三个维度组织的:
进一步的,个人理解,三大核心问题又可以聚焦于2大点:
抓住这2点,就可以由点及线,把整个并发编程体系串联起来。个人理解,其实线程池部分严格说来应该属于并行编程。
ps.并发 VS 并行 ?
管程是一把解决并发问题的万能钥匙。所谓管程,指的是管理共享变量以及对共享变量的操作过程,让他们支持并发。翻译为 Java 领域的语言,就是管理类的成员变量和成员方法,让这个类是线程安全的。
在管程模型里,共享变量和对共享变量的操作是被封装起来的,当多个线程同时试图进入管程内部时,只允许一个线程进入,其他线程则在入口等待队列中等待。 ----解决了互斥
条件变量和等待队列的作用----解决线程同步问题
java语言内置的管程(synchronized)对 MESA 管程模型进行了精简。MESA 模型中,条件变量可以有多个,synchronized只有一个条件变量,只支持非公平锁。
正是由于synchronized的局限性,才有了JUC包中的各种lock,JUC包中的AQS就是对MESA管程的实现,然后基于AQS延伸开发出了各种lock和并发工具类,其核心思想的源头都是管程!
降低延迟,提高吞吐量
线程池基本原理:美团的这篇文章讲的很好---Java线程池实现原理及其在美团业务中的实践
多线程优化性能的目标说白了就是2点,降低延迟,提高吞吐量,具体做法就是串改并,串行转换成并行的过程中,一定会涉及到异步化。异步化,是并行方案得以实施的基础。
简单的并行任务-----------------------------------------> 线程池 +Future
任务之间有聚合关系(AND 聚合/OR 聚合)--------------------> CompletableFuture (强烈推荐使用!!!)
分治 -------------------------------------------------> Fork/Join (适合处理一些特殊场景,并行计算 海量数据处理)
一些线程池的骚操作:
美团动态线程池
按某个维度顺序执行任务的线程池
内存安全的阻塞队列
原生线程池拒绝策略的bug