在java多线程开发中,一般使用线程的时候都是创建一个Thread对象,然后调用start方法执行,这样做没有什么问题,但是如果有多任务并发执行的时候,你可能需要频繁地创建多个线程来执行任务,这样会造成性能方面的问题,体现如下:
1.大量的线程的创建和销毁,本身就是一个很大的性能开销
2.大量线程同时运作的时候,会造成资源紧张,我们知道线程的底层机制就是切分CPU的时间,在大量线程互相抢占资源的时候,可能会造成阻塞现象
基于上面的原因,JDK为我们提供了线程池。线程池可以帮我们管理一定数量的线程,通过重复使用线程来避免大量线程的创建和销毁,从而提高了线程的使用效率
线程池的使用:
关于线程池,首先要了解ThreadPoolExecutor
类,创建线程池就是通过这个类去创建的,它的构造函数如下:
public ThreadPoolExecutor(int corePoolSize, //核心线程数量
int maximumPoolSize, //最大线程数量
long keepAliveTime, //非核心线程的空余存活时间
TimeUnit unit, //存活时间的单位
BlockingQueue<Runnable> workQueue, //保存待执行任务的队列
ThreadFactory threadFactory, //创建新线程使用的工厂
RejectedExecutionHandler handler // 当任务无法执行时的处理器
) {
}
下面来详细解析一下各个参数的含义:
1.corePoolSize (核心线程数量)
默认情况下,核心线程会一直处于存活状态,即使它们是闲置的。如果将ThreadPoolExecutor的allowCoreThreadTimeOut属性设置为true,那么核心线程也会在超时之后结束,超时时间就是参数中设置的keepAlivTime的值
值得注意的是,当线程数量小于核心线程数时,有任务要执行时,即使当前有空闲线程也会创建一个新的核心线程
2.maximumPoolSize(最大线程数量)
包括核心线程数 + 非核心线程数量,如果任务队列满的情况下,并且线程总数小于最大线程数,此时会创建一个新的线程来执行任务
3.keepAliveTime(非核心线程的存活时间)
意思是非核心线程在没有任务执行的情况下的最大的存活时间,也就是说非核心线程在空闲了一定时间以后就会挂掉,当然如果线程池设置 allowCoreThreadTimeOut(true)
,核心线程也一样会有这种存活期限
4.unit (存活时间单位)
5.workQueue(任务队列)
线程池中的任务队列,我们提交给线程池的Runnable任务就保存在这个队列中。这是一个BlockQueue类型的结构,属于阻塞队列, 类似于生产者消费者模式,队列中有任务的时候才能进行取出,当队列满的时候,添加也会被阻塞
6.threadFactory(创建线程的工厂)
通过这个工厂类,我们可以给创建线程取名字或者优先级之类的参数
7.handler (任务饱和策略)
主要有四种策略:
CallerRunsPolicy:只要线程池没有关闭,就直接用调用者所在线程来运行任务
AbortPolicy:直接抛出RejectedExecutionException异常
DiscardPolicy:不通知地把任务抛弃了,不干了
DiscardOldestPolicy:把队列中呆了最久的那个任务抛弃了,然后再调用execute方法重试
workQueue(任务队列)的分析:
线程池中使用的队列是BlockQueue接口,常用的实现有以下几种:
1.ArrayBlockingQueue:基于数组,有界,先进先出原则,一般不用
2.LinkedBlockingQueue:基于链表,按先进先出排序,Executors.newFixedThreadPool() 使用的就是个队列
3.SynchronousQueue:这个队列不保存任务,只负责传递,Executors.newCachedThreadPool就使用了这个队列,当有任务到来时如果当前没有空闲的线程,就会创建一个线程来执行新任务
4.PriorityBlockingQueue:具有优先级的任务队列
下面我们封装一个自己的线程池,代码如下:
public class MyThreadPool {
private final String TAG = this.getClass().getSimpleName();
// 核心线程数为 CPU数*2
private static final int CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2;
private static final int MAXIMUM_POOL_SIZE = 64; // 线程队列最大线程数
private static final int KEEP_ALIVE_TIME = 1; // 保持存活时间 1秒
//任务队列
private final BlockingQueue<Runnable> mWorkQueue = new LinkedBlockingQueue<>(128);
//创建线程的工厂
private final ThreadFactory DEFAULT_THREAD_FACTORY = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
Thread thread =