1、线程池简介
线程池主要解决两个问题:一是当执行大量异步任务时线程池能够提供较好的性能。在不使用线程池时,每当需要执行异步任务时直接new一个线程来运行,而线程的创建和销毁是需要开销的。线程池里面的线程是可复用的,不需要每次执行异步任务时都重新创建和销毁线程。二是线程池提供了一种资源限制和管理手段,比如可以限制线程的个数,动态新增线程等。
2、java中提供的线程池
Executors类提供了四种不同的线程池:newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor。
2.1、newCachedThreadPool:
用来创建一个可以无限扩大的线程池(线程池个数最多可以达到Integer.MAX_VALUE,线程自动回收),适用于负载较轻的场景,执行短期异步任务。
2.2、newFixedThreadPool:
创建一个固定大小的线程池,每次提交任务就创建一个线程,直到线程达到线程池的容量。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
2.3、newSingleThreadExecutor:
创建一个单线程的线程池,这个线程池只有一个线程工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
2.4、newScheduledThreadPool:
指定一定延迟时间后或者定时进行任务调度执行的线程池。
3、常见操作
3.1、shutdown操作
调用shutdown方法后,线程池就不会再接受新任务了,但是工作队列里面的任务还是要执行的。该方法会立刻返回,并不等待队列任务完成再返回。
3.2、shutdownNow操作
调用shutdownNow方法后,线程池就不会再接受新的任务了,并且会丢弃工作队列里面的任务,正在执行的任务会被中断,该方法会立刻返回,并不等待激活的任务执行完成。返回值位这时候队列里面被丢弃的任务列表。
3.3、awaitTermination操作
当线程调用awaitTermination方法后,当前线程会被阻塞,直到线程池状态位TERMINATED才返回,或者等待时间超时才返回。
4、总结
线程池巧妙地使用一个Integer类型的原子变量来记录线程池状态和线程池中的线程个数。通过线程池状态来控制任务的执行,每个worker线程可以处理多个任务。线程池通过线程的复用减少了线程的创建和销毁的开销。