第三篇Java技术分享(三探JUC-锁与线程池)
Jpunster
前文:在开始正文之前,首先恭喜本作者斩获大厂offer,在更新完JUC之后会总结下最近的面试题分享给大家。
闲话少说,先解决上篇文章留下的小问题。
1.8锁文章中讲到不要显式创建线程,要使用线程池来创建线程。
2.线程池创建线程时,不要使用Executor来创建线程池要使用ThreadPoolExecutor来创建。
那么为什么不要显示创建线程,以及为什么不要用Executor来创建线程而要用底层ThreadPoolExecutor来创建线程呢?
答:我们先看下阿里巴巴Java开发手册:
(先来解释下名词。FixedThreadPool:固定线程池,SingleThreadPool:单个线程,CachedThreadPool:可伸缩线程池,ScheduledThreadPool:定时线程池)
(1)使用线程池的优点: 1、低资源的消耗2、提高响应的速度3、方便管理。线程复用、可以控制最大并发数、管理线程。
(2)如果使用Executor来创建线程池,默认允许创建线程数量为Intgeer.MAX_VALUE,约为21亿,所以可能会创建大量线程,从而导致OOM。(需要学习JVM调优的,作者会在更新完近几期文章后讲解下通常使用的方法。先埋小坑。)
2.8锁文章最后提到,如何在面试时很简单的写一个死锁?
答:什么是死锁,如何避免死锁,手写一个死锁,这些是面试官在面试初中级开发时问的常见问题。我们首先要避免死锁产生,在遇到死锁问题时要快速定位,快速解决。这里提一下死锁解决可以通过看日志,堆栈信息(下面讲解)来进行排查。接下来我们来手写一个死锁。
总结:lockA去获得lockB,lockB去获得lockA这样就造成了死锁。
正文:
1.各种锁的理解锁
<1>前文说了死锁,我们先来解决如何排查死锁。
(1)看日志
(2)查看堆栈信息
接前文例子:通过jps-l 查看运行进程 通过jstack 进程号 来查看堆栈信息
我们发现T2线程拿到以3298结尾的锁等待3260结尾的锁,T1线程拿到以3260结尾的锁等待3298的锁,所以就造成了死锁现象。这样我们就能更快的排查死锁产生的原因。
<2>公平锁,非公平锁
公平锁:非常公平, 不能够插队,必须先来后到!
非公平锁:非常不公平,可以插队 (默认都是非公平)
<3>可重入锁
可重入锁(递归锁)就是拿到外层的锁,就可以自动获得里面的锁。
结果如我们预期:拿到外层的锁,就可以自动获得里面的锁。
<4>自旋锁
TIPS:自旋锁在CAS中使用,下篇文章我们讲CAS时,在一并详解。
2.线程池:jdk自带三大方法、7大参数、4种拒绝策略
<1>三大常用方法:FixedThreadPool:固定线程池,SingleThreadPool:单个线程,CachedThreadPool:可伸缩线程池。
<2>7大参数
我们来分析一下这7大参数。
<3>4种拒绝策略
总结:JDK中线程池和锁暂时先介绍到这里。前三篇文章知识点有点密集,以后尽量做到拆开详解重要知识点。
后台回复:阿里巴巴即可获得阿里开发手册哦~
下篇预告:分布式锁以及CAS(深入理解),JUC的也就告一段落了。