ThreadPoolExector(线程池)

线程池ThreadPoolExecutor的优点

1.重用线程池的线程,可以避免因为线程的创建和销毁所带来的性能开销。

2.可以控制线程池的线程最大并发数量,避免线程之间因为互相抢占资源而造成的阻塞。

3.能够对线程进行简单的管理,并提供定时执行以及间隔执行等功能。

首先简单分析一下ThreadPoolExecutor的构成参数:

public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable>workQueue,
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<Runnable> 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<Runnable>());
   }

2. CachedThreadPool:

通过newCachedThreadPool方法创建,它是一种线程数量不固定的线程池,它只有没核心线程,线程数为Interget.MAX_VALUE,当线程池的线程都处于活动状态时,线程池会创建新的线程来处理任务,否则会调用空闲线程处理,超时时长为60秒。它的任务队列相当于一个空集合,任何任务都会被执行,适合执行量大耗时较少的任务。

 public static ExecutorService newCachedThreadPool(){
        return new ThreadPoolExecutor(0,Integer.MAX_VALUE,60,TimeUnit.SECONDS,new SynchronousQueue<Runnable>());
    }

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>());
    }

常规用法实例:

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<Runnable>(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;
        }
    }


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值