目录
线程池的创建方式
线程池的优势
Runable和Callable接口的区别
java的几种线程池
线程池的七大参数
线程池底层工作原理
线程的拒绝策略
手写线程池
如何确定这些参数?
死锁编码及定位分析
线程池的创建方式:
(1)继承Thread类;很少用,实际都是面向接口编程。
(2)实现Runable接口 ; (3)实现Callable接口(JDK>=1.5);(4)线程池创建。
线程池的优势
Runable和Callable接口的区别:
1. Runable没有返回值,Callable接口有返回值;
2.接口实现的方法不一样,Runable实现run方法,Callable实现call方法;
3.Callable可以声明抛出异常。
发现没有一个Thread实现了Callable接口,都是runnable接口,于是要通过一个中间件适配器即实现了runnable接口有实现了callable接口,即futureTask方法
线程池是通过Executor框架实现的,该框架中Executor,Executors(工具类),ExecutorService
其中三个工具类:Array Arrays(Arrays.aslist());Collection Collections; Executor Executors.
线程池的底层就是ThreadPoolExecutor类
java的几种线程池
1.executors.newFixedThreadPool(int); 执行长期的任务
2.executors.newSingleThreadExecutor; 一个任务执行
3.executors.newCachedThreadpool(); 执行短期异步或负载较轻任务
创建:ExecutorService threadPool=Executors.newFixedThreadPool(int) 但是这三种底层都是通过ThreadPoolExecutor类实现的。但阿里巴巴规范里,这三个都不用而是手写线程池。
线程池的七大参数
主要五个:
corePoolSize 线程池中常驻核心线程数,当值窗口数,超过这个数就会放到缓存队列
maximumPoolSize 线程池能容纳最大的线程数
keepAliveTime 多余的空闲线程的存活时间,超过corePoolSize的线程数叫空闲线程
Unit keepAliveTime的单位
BlockingQueue 任务队列,被提交但还未执行的任务,阻塞队列也是有限的数量
另外两个:
ThreadFactory 表示生产线程池工作线程的工厂,用来创建线程,一般用默认的
RejectedExecutionHandler 拒绝策略,如果阻塞也满了就拒绝,有四种拒绝策略
线程池底层工作原理
1.创建线程池,等待提交过来的任务请求。
2.添加任务请求时,分为以下几种情况:
2.1如果正在运行的线程数量小于corePoolSize,就创建线程处理
2.2 如果大于corePoolSize,就将任务放入阻塞任务队列
2.3 如果队列满了但线程数量小于maximumPoolSize,就创建非核心线程去处理任务
2.4 如果队列满了且正在运行的数量大于等于maximumPoolSize,就启动饱和拒绝策略
3.当一个线程完成任务,就会从队列取下一个
4.当一个线程一定时间内没有任务处理,就会判断
如果运行数大于corePoolSize,就被停掉;所以最后会减小到corePoolSize的数量大小。
线程的拒绝策略
callerRunsPolicy就是把超过的线程给调用的如main线程。
手写线程池如何确定这些参数?
1.CPU密集型任务配置尽可能少的线程数量,尽量减少切换:CPU核数+1个线程的线程池
2.IO密集型:
(1)由于IO并不是一直在执行任务,则应配置尽可能多的线程,如CPU核数*2;
(2)CPU核数/(1-阻塞系数)阻塞系数在0.8到0.9间
死锁编码及定位分析
死锁的排查:
1. jps:类似Linux的ps -ed|grep xxx 查看Java的进程 jps -l查看出事的进程编号
2. jstack 调用jstack 进程编号 命令,是不是死锁,看栈的问题
参考:尚硅谷面试整理
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)