Skip to the content.

Android 线程池 ExecutorService

  1. ThreadPoolExecutor

Handler发送Message到MessageQueue中保存,Looper会不断的从MessageQueue中获取Message,然后调用与Message绑定Handler的dispatchMessage方法,最终调用会handleMessage进行真正消息处理

Executor作为一个接口,它的具体实现就是ThreadPoolExecutor。

Android中的线程池都是直接或间接通过配置ThreadPoolExecutor来实现不同特性的线程池。

/* 
*@ ThreadPoolExecutor构造参数介绍 
*/  
public ThreadPoolExecutor(  
//核心线程数,除非allowCoreThreadTimeOut被设置为true,否则它闲着也不会死  
int corePoolSize,   
//最大线程数,活动线程数量超过它,后续任务就会排队                     
int maximumPoolSize,   
//超时时长,作用于非核心线程(allowCoreThreadTimeOut被设置为true时也会同时作用于核心线程),闲置超时便被回收             
long keepAliveTime,                            
//枚举类型,设置keepAliveTime的单位,有TimeUnit.MILLISECONDS(ms)、TimeUnit. SECONDS(s)等  
TimeUnit unit,  
//缓冲任务队列,线程池的execute方法会将Runnable对象存储起来  
BlockingQueue<Runnable> workQueue,  
//线程工厂接口,只有一个new Thread(Runnable r)方法,可为线程池创建新线程  
ThreadFactory threadFactory)

1.execute一个线程之后,如果线程池中的线程数未达到核心线程数,则会立马启用一个核心线程去执行。

2.execute一个线程之后,如果线程池中的线程数已经达到核心线程数,且workQueue未满,则将新线程放入workQueue中等待执行。

3.execute一个线程之后,如果线程池中的线程数已经达到核心线程数但未超过非核心线程数,且workQueue已满,则开启一个非核心线程来执行任务。

4.execute一个线程之后,如果线程池中的线程数已经超过非核心线程数,则拒绝执行该任务,采取饱和策略,并抛出RejectedExecutionException异常。

队列会满,此时会开启2个非核心线程来执行剩下的两个任务。
  1. FixedThreadPool (可重用固定线程数)
public static ExecutorService newFixThreadPool(int nThreads){  
    return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());  
}  
//使用  
Executors.newFixThreadPool(5).execute(r);

特点:参数为核心线程数,只有核心线程,无非核心线程,并且阻塞队列无界。

FixThreadPool其实就像一堆人排队上公厕一样,可以无数多人排队,但是厕所位置就那么多,而且没人上时,厕所也不会被拆迁,由于线程不会回收,FixThreadPool会更快地响应外界请求

  1. SingleThreadPool(单个核线的fixed)
    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

    //创建
    ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();

由于只有一个核心线程,当被占用时,其他的任务需要进入队列等待。 可以把SingleThreadPool简单的理解为FixThreadPool的参数被手动设置为1的情况,即Executors.newFixThreadPool(1).execute(r)。

  1. CachedThreadPoo(按需创建) ```java

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

 ExecutorService singleThreadPool = Executors.newCachedThreadPool(); ``` 没有核心线程,只有非核心线程,并且每个非核心线程空闲等待的时间为60s,采用SynchronousQueue队列 CachedThreadPool只有非核心线程,最大线程数非常大,所有线程都活动时,会为新任务创建新线程,否则利用空闲线程(60s空闲时间,过了就会被回收,所以线程池中有0个线程的可能)处理任务 任务队列SynchronousQueue相当于一个空集合,导致任何任务都会被立即执行

比较适合执行大量的耗时较少的任务。喝咖啡人挺多的,喝的时间也不长。

  1. ScheduledThreadPool(定时延时执行)
        public ScheduledThreadPoolExecutor(int corePoolSize) {
         super(corePoolSize, Integer.MAX_VALUE,
               DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
               new DelayedWorkQueue());
     }
    
     DEFAULT_KEEPALIVE_MILLIS =10 
    
     //使用,延迟1秒执行,每隔2秒执行一次Runnable r  
      Executors. newScheduledThreadPool (5).scheduleAtFixedRate(r, 1000, 2000, TimeUnit.MILLISECONDS);
    

    核心线程数固定,非核心线程(闲着没活干会被立即回收)数没有限制。

从上面代码也可以看出,ScheduledThreadPool主要用于执行定时任务以及有固定周期的重复任务。

    ArrayBlockingQueue 一个由数组结构组成的有界阻塞队列
    LinkedBlockingQueue 一个由链表结构组成的有界阻塞队列
    PriorityBlockingQueue 一个支持优先级排序的无界阻塞队列
    DelayQueue一个使用优先级队列实现的无界阻塞队列
    SynchronousQueue一个不存储元素的阻塞队列
    LinkedTransferQueue一个由链表结构组成的无界阻塞队列
    LinkedBlockingDeque一个由链表结构组成的双向阻塞队列

1.shutDown()  关闭线程池不影响已经提交的任务

2.shutDownNow() 关闭线程池并尝试去终止正在执行的线程

3.allowCoreThreadTimeOut(boolean value) 允许核心线程闲置超时时被回收

4.submit 一般情况下我们使用execute来提交任务但是有时候可能也会用到submit使用submit的好处是submit有返回值

5.beforeExecute() - 任务执行前执行的方法

6.afterExecute() -任务执行结束后执行的方法

7.terminated() -线程池关闭后执行的方法

https://blog.csdn.net/l540675759/article/details/62230562

https://www.jianshu.com/p/7b2da1d94b42

ScheduledExecutorService 将定时任务与线程池功能结合

// 延时1秒钟执行
        mScheduledExecutorService.schedule(threadFactory.newThread(new Runnable() {
            @Override
            public void run() {
                Log.e("jayqiu", "first task");
            }
        }), 1, TimeUnit.SECONDS);


 // 循环任务,按照上一次任务的发起时间计算下一次任务的开始时间
        mScheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                Log.e("jayqiu", "first:" + System.currentTimeMillis() / 1000);
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, 1, 1, TimeUnit.SECONDS);

// 循环任务,以上一次任务的结束时间计算下一次任务的开始时间
        mScheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                Log.e("jayqiu", "scheduleWithFixedDelay:" + System.currentTimeMillis() / 1000);
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, 1, 1, TimeUnit.SECONDS);