android 线程池(上)

1,335 阅读4分钟

针对android中的多线程请求,本文主要介绍 android中线程池的基本使用。

1:线程池的分类

FixedThreadPool:它是一种线程数量固定的线程池,当线程处于空闲状态时,它们并不会被回收,除非线程池被关闭,当所有的线程都处于活动状态时,新任务都会处于等待状态,直到有线程空闲出来。该线程池中只有核心线程,并且这些核心线程不会被回收,这意味着它能够更加快速的响应外界的请求。
CachedThreadPool: 该线程池中线程数量不固定,并且内部只有非核心线程,其线程的最大值为 Integer.MAX_VALUE。所以可以认为该线程池中的线程数量可以任意大。该线程池的特定是当线程池中的线程都处于活动状态时,线程池会创建新的线程来处理新的任务,否则就会利用空闲的线程来处理新的任务。该线程池中的空闲线程都有超时机制,这个超时时长为 60s ,超过60s 空闲线程就会被回收。
ScheduledThreadPool: 该线程池中包含核心线程以及非核心线程,核心线程数量是固定的,而非核心线程数量是没有限制的,并且当非核心线程闲置时会被立即回收。
SingleThreadExecutor:该线程池是一个单例线程,其内部只有一个核心线程。

2:线程池的基本使用

FixedThreadPool:

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4)
fixedThreadPool.execute(runnable)

CachedThreadPool:

 ExecutorService cacheThreadPool = Executors.newCachedThreadPool()
 cacheThreadPool.execute(runnable)

ScheduledThreadPool:

 ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(4)
 scheduledThreadPool.schedule(runnable3, 2000, TimeUnit.MILLISECONDS)

SingleThreadExecutor:

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor()
singleThreadExecutor.execute(runnable)

3: 线程池构造解析

android中线程池概念来源于java中的Executor,而Executor通过源码我们可以看出是一个接口;

public interface Executor {
    void execute(Runnable command);
}

内部只包含一个抽象方法 execute(….);

同时android中 重新定义了ExecutorService接口去继承上述接口;

public interface ExecutorService extends Executor{}

而 ExecutorService 接口的实现类是:

public abstract class AbstractExecutorService implements ExecutorService{}

抽象类AbstractExecutorService 的具体实现是:

public class ThreadPoolExecutor extends AbstractExecutorService{}

通过上述关系可以看到线程池的真正实现为ThreadPoolExecutor,在ThreadPoolExecutor 中提供了一系列的参数来创建不同的线程池。
下面我们来看ThreadPoolExecutor的构造函数:

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {}

内部参数:

corePoolSize:线程的核心线程数;
maximumPoolSize:线程池所能容纳的最大线程数:
keepAliveTime:非核心线程闲置时的超时市场,超过这个时长非核心线程就会被回收
unit:用于指定keepAliveTime 的单位
workQueue:线程池中的任务队列
threadFactory:线程工厂,为线程池提供创建新线程的功能
handler:当线程池无法执行新的任务时,会调用handler的rejectedEcexutor方法来通知调用者。该参数不常用,可以忽略。
通过源码我们可以看到google是通过工厂方式去创建各种线程池,具体源码我们可以通过

public class Executors{}

该类可以看到内部通过各种方法去获取不同的线程池。

下面我们根据Executors 中各个方法去看各个线程池是如何实现的。

FixedThreadPool:

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue());
    }

FixedThreadPool 通过调用 ThreadPoolExecutor构造函数 可以看出实质上是通过外部设置了 核心线程数,以及非核心线程数。
CachedThreadPool:

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

CachedThreadPool 内部可以看出实质上 核心线程数为0 ,而非核心线程数为Int最大值
SingleThreadExecutor:

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue()));
    }

SingleThreadExecutor 可以看出实质上是核心线程数以及非核心线程数均为1;

ScheduledThreadPool:

 public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }


public class ScheduledThreadPoolExecutor
        extends ThreadPoolExecutor
        implements ScheduledExecutorService {
        ....
         public ScheduledThreadPoolExecutor(int corePoolSize) {
                super(corePoolSize, Integer.MAX_VALUE,
                      DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
                      new DelayedWorkQueue());
            }
            ....
    }

ScheduledThreadPool 可以看出核心线程数是通过外部设置,而非核心线程数实质是int的最大值。

4 : 线程池的基本执行流程

1:如果线程池中核心线程未达到上限那么,则会直接启动一个核心线程去执行任务;
2:如果核心线程达到上限,那么会将任务放到任务队列中,等待执行,
3:如果任务无法插入到任务队列中,则会开启一个非核心线程去执行任务,
4:如果线程池中的线程已经达到线程数量的上限,则将不会去执行任务,ThreadPoolExecutor将会调用RejectedExecutionHandler的rejectedExecution方法通知调用者。

以下通过图示来说明:

这里写图片描述