线程池的使用
获取线程池的方式有两种:
-
利用工具类Executors里面的静态方法
-
自己new对象
创建池子
Executors类中有个创建线程池的方法如下:
-
public static ExecutorService newFixedThreadPool(int nThreads)
:返回线程池对象。(创建的是有上限的线程池,也就是池中的线程个数可以指定最大数量)
-
public static ExecutorService newCachedThreadPool()
:返回线程池对象。
ThreadPoolExecutor pool = new ThreadPoolExecutor(
5,
10,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(10),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
直接创建ThreadPoolExecutor的对象即可。
参数分析:
-
参数一:核心线程数量(不能小于0)
-
参数二:最大线程数(不能小于等于0,最大数量 >= 核心线程数量)
-
参数三:空闲线程最大存活时间(不能小于0)
-
参数四:时间单位(时间单位)
-
参数五:任务队列(不能为null)
-
参数六:创建线程工厂(不能为null)
-
参数七:任务的拒绝策略(不能为null)
队列的种类
队列分为两种,有界和无界
-
ArrayBlockingQueue:有界队列,我们在创建对象的时候可以指定上限,也必须指定上限
-
LinkedBlockingQueue:无界队列,但是事实上还是有界的,只不过队伍可以很长,int的最大值21亿多
任务的拒绝策略
分为四种:
-
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常,是默认的策略
-
ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常 这是不推荐的做法
-
ThreadPoolExecutor.DiscardOldestPolicy:抛弃队列中等待最久的任务 然后把当前任务加入队列中
-
ThreadPoolExecutor.CallerRunsPolicy:调用任务的run()方法绕过线程池直接执行。
临时线程创建时机
新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程。
注意:核心线程在忙,再有任务提交,先排队,队伍满了,再开临时线程。
触发拒绝策略时机
核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始任务拒绝
简单理解:所有的都满了,才会拒绝。