Android基础-使用线程池

200 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情

为何使用线程池

之前提到过在Android中使用Thread。但Thread使用存在一些问题(频繁创建影响性能、线程资源不可控、多线程竞争无优先级等)缺少一些更细粒度主观控制能力。因此统一使用线程池可以很好帮助开发者去控制线程使用:多线程统一管理、减少资源竞争紧张问题;线程可复用性,减少频繁创建线程带来GC等性能问题。

线程池介绍

线程池的使用会使用到ExecutorServiceExecutors两个类。ExecutorService是接口类继承了Executors接口。Executors则实现提供了四种线程池形式,分别为newFixedThreadPoolnewCachedThreadPoolnewSingleThreadPoolnewScheduledThreadPool

newFixedThreadPool

该线程池是创建可复用固定线程数的线程池。根据需要创建线程数,执行固定个数线程。超出线程范围的任务会在队列中等待其他线程结束后再执行,线程数则是固定数量且可复用。

ExecutorService executorService = Executors.newFixedThreadPool(5);
for(int i = 0; i < 10;i++){
    Runnable runnable = new Runnable(){
           @Override
           public void run(){
              // xxx
           }
    };
    executorService.execute(runnable);
}

newCachedThreadPool

该线程为可缓存线程池,线程池长度超出需求会灵活回收闲置线程。可缓存线程池大小不定,可根据需要创建不同数量线程。该类型线程池比较适用于轻量级异步任务。

ExecutorService executorService = Executors.newCachedThreadPool();
for(int i = 0; i < 10;i++){
    Runnable runnable = new Runnable(){
           @Override
           public void run(){
              // xxx
           }
    };
    executorService.execute(runnable);
}

newSingleThreadPool

该线程池就是单一线程池,内部只有一个线程对象。可以理解等同于Executors.newFixedThreadPool(1);每次处理一个异步任务,其他任务在单联队列中等待被处理。

ExecutorService executorService = Executors.newSingleThreadPool();
for(int i = 0; i < 10;i++){
    Runnable runnable = new Runnable(){
           @Override
           public void run(){
              // xxx
           }
    };
    executorService.execute(runnable);
}

newScheduledThreadPool

该线程池特点是支持执行定时和周期性任务,可通过调用schedule方法设置定时性任务。

ExecutorService executorService = Executors.newScheduledThreadPool(5);
for(int i = 0; i < 10;i++){
    Runnable runnable = new Runnable(){
           @Override
           public void run(){
              // xxx
           }
    };
    executorService.schedule(runnable,1000,TimeUnit.MILLISECONDS);
}

自定义ThreadPoolExecutor

除了上述介绍的线程池之外,开发者可根据实际业务需求自定义线程池来使用。

  • corePoolSize:核心线程数
  • maximumPoolSize:线程池最大数
  • keepAliveTime:空闲线程存活时间(超出时间会被回收)
  • unit:存活时间单位
  • workQueue:等待执行的任务队列
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), defaultHandler);
}

线程池总结

newFixedThreadPoolnewCachedThreadPoolnewSingleThreadPoolnewScheduledThreadPool
核心线程和非核心线程数量相等没有核心线程、只有无限非核心线程核心线程只有一个核心线程固定,非核心线程无限
线程空闲不会被回收非核心线程结束后60s后回收非核心线程会在闲置状态下回收

拒绝策略

在线程池中若任务数超出线程池所能容纳的数量时会触发拒绝策略。

  • AbortPolicy:默认策略,丢弃任务并抛出异常
  • DisCardPolicy:丢弃但不会抛出异常
  • DisCardOldesPolicy:竞争第一个任务,丢弃队列最前面的任务,成功等于执行;失败就丢弃不抛出异常
  • CallerRunsPolicy:在调用者所在线程去执行提交的任务。