线程池ThreadPoolExecutor的优点:
1.重用线程池的线程,可以避免因为线程的创建和销毁所带来的性能开销。
2.可以控制线程池的线程最大并发数量,避免线程之间因为互相抢占资源而造成的阻塞。
3.能够对线程进行简单的管理,并提供定时执行以及间隔执行等功能。
首先简单分析一下ThreadPoolExecutor的构成参数:
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime, TimeUnit unit, BlockingQueueworkQueue,
ThreadFactory threadFactory){
}
corePoolSize
线程池的核心线程数,默认情况下,核心线程会一直在线程池中存活下来,既是是处于闲置状态,。如果将ThreadPoolExecutor的allowCoreThreadTImeOut属性设置为true,超时了核心线程也会被终止,这个时间有 keepAliveTime决定。
maximumPoolSize
线程池容纳的最大线程数,当活动的线程数量达到上限后,后续的任务将会阻塞。
keepAliveTime
非核心线程可以闲置的时间,超过这个时间,非核心线程会被回收。如果如果将ThreadPoolExecutor的allowCoreThreadTImeOut属性设置为true,核心线程也会回收。
unit
用于指定keepAliveTime的时间单位,只是一个枚举,常用的有TimeUnit.MILLISECONDS,TimeUnit.SECONDS(秒),TimeUnit.MINUTES(分钟)
workQueue
线程池中的任务队列,通过线程池的execute()方法提交的Runnable对象会存储在这个参数中。
threadFactory
线程工厂,为线程池创建新的线程,它是一个接口,只有一个方法:ThreadnewThread(Runnable)。还有一个方法RejectedExecutionHandler 是当任务队列已满或者无法成功执行任务时会调用,报错的,这里不再单独介绍。
ThreadPoolExecutor会遵循以下原则:
1)如果线程池的线程数量没有达到核心线程的数量,会直接启动一个核心线程去执行任务。
2)如果线程池的线程数量已经达到或者超过核心线程池的数量,那么任务会被插到任务队列中排队执行。
3)如果在步骤2中任务没有插入到任务队列中,说明任务队列已经排满,如果线程池中的线程数量没有达到最大线程数量,会启动一个非核心线程来执行任务。
4)如果步骤3中的线程池中的线程数量已经达到最大值,就会拒绝执行。
ThreadPoolExecutor在AsyncTask的源码中有具体提下:
private static final int CPU_COUNT =Runtime.getRuntime().availableProcessors();
private static final int COPE_POOL_SIZE =CPU_COUNT+1;
private static final int MAXIMUM_POOL_SIZE =CPU_COUNT*2+1;
private static final int KEEP_ALIVE =1;
private static final ThreadFactory mThreadFactory = new ThreadFactory() {
private final AtomicInteger mInteger = new AtomicInteger(1);
@Override
public Thread newThread(Runnable r) {
return new Thread(r,"AsyncTask #"+mInteger.getAndIncrement());
}
};
private static final BlockingDeque mWorkQueue = new LinkedBlockingDeque<>(128);
public static final Executor threadPoolExector = new ThreadPoolExecutor(COPE_POOL_SIZE,MAXIMUM_POOL_SIZE,KEEP_ALIVE, TimeUnit.SECONDS
,mWorkQueue,mThreadFactory);
ThreadPoolExecutor的分类
1.FixedThreadPool
通过newFixedThreadPool方法来创建。它是一种线程数量固定的线程池,只有核心线程,线程处于空闲状态不会回收,除非线程池关闭。并且该线程池内的核心线程没有超时限制,任务队列也没有限制;
public static ExecutorService newFixedThreadPool(int threads){
return new ThreadPoolExecutor(threads,threads,0L,TimeUnit.SECONDS,new LinkedBlockingDeque());
}
2. CachedThreadPool:
通过newCachedThreadPool方法创建,它是一种线程数量不固定的线程池,它只有没核心线程,线程数为Interget.MAX_VALUE,当线程池的线程都处于活动状态时,线程池会创建新的线程来处理任务,否则会调用空闲线程处理,超时时长为60秒。它的任务队列相当于一个空集合,任何任务都会被执行,适合执行量大耗时较少的任务。
public static ExecutorService newCachedThreadPool(){
return new ThreadPoolExecutor(0,Integer.MAX_VALUE,60,TimeUnit.SECONDS,new SynchronousQueue());
}
3. ScheduledThreadPool
通过newScheduledThreadPool方法创建,它的核心线程数量是固定的,非核心线程数量是不固定的,非核心线程空闲时立即回收。适合执行定时任务和具有固定周期的重复任务。
public static public static ScheduledExecutorService newScheduledThreadPool(int threads){
return new ScheduledThreadPoolExecutor(threads);
}
public ScheduledThreadPoolExecutor(int corePoolSize){
super(corePoolSize,Integer.MAX_VALUE,0,TimeUnit.NANOSECONDS,new DelayedWorkQueue());
}
4. SingleThreadPool
通过newSingleThreadPool来创建,线程池中只有一个核心线程,所有的任务都在一个线程中按顺序执行,不需要考虑同步的问题。
public static ExecutorService newSingelThreadPool(){
return new ThreadPoolExecutor(1,1,0L,TimeUnit.SECONDS,new LinkedBlockingDeque());
}
常规用法实例:
Runnable mRunnable = new Runnable() {
@Override
public void run() {
//TODO
}
};
public void setThreadPool(){
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);
fixedThreadPool.execute(mRunnable);
ExecutorService cachedThreadPool =Executors.newCachedThreadPool();
cachedThreadPool.execute(mRunnable);
ScheduledExecutorService scheduledExecutorService =Executors.newScheduledThreadPool(4);
//延时200毫秒执行
scheduledExecutorService.schedule(mRunnable,200,TimeUnit.MILLISECONDS);
//延迟10毫秒,每1000毫秒执行一次
scheduledExecutorService.scheduleAtFixedRate(mRunnable,10,1000,TimeUnit.MILLISECONDS);
ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
singleThreadPool.execute(mRunnable);
}
提供一种封装好的ThreadPoolUtil:
public class ThreadPoolUtil {
public final static ThreadPoolExecutor mThreadPoolExecutor;
private final static int corePoolSize = 4;
private final static int KEEP_ALIVE_TIME = 60 * 1000;
private final static String CUSTOM_THREAD_NAME = "";
static {
mThreadPoolExecutor = new ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE, KEEP_ALIVE_TIME,
TimeUnit.SECONDS, new SynchronousQueue(true), new CustomFactory(Thread.NORM_PRIORITY));
}
public static void execute(Runnable runnable) {
mThreadPoolExecutor.execute(runnable);
}
public static void cancle(Runnable runnable) {
mThreadPoolExecutor.remove(runnable);
}
private static class CustomFactory implements ThreadFactory {
int mPriority;
ThreadGroup mThreadGroup;
private AtomicInteger mInteger = new AtomicInteger(1);
public CustomFactory(int normal) {
this.mPriority = normal;
mThreadGroup = Thread.currentThread().getThreadGroup();
}
@Override
public Thread newThread(Runnable r) {
Thread mThread = new Thread(mThreadGroup, r, CUSTOM_THREAD_NAME + mInteger.getAndIncrement(), 0);
mThread.setPriority(mPriority);
return mThread;
}
}