Android中线程池的使用

本文介绍Android中线程池ThreadPoolExecutor的使用方法,包括创建线程池、设置任务优先级和取消任务等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文来自:Amit Shekhar的一篇译文,地址
https://medium.freecodecamp.com/threadpoolexecutor-in-android-8e9d22330ee3#.c451hqaf2

本文主要讲解线程池、线程池Executor在Android的使用,并且通过代码片段来覆盖这些主题。
这里写图片描述

线程池(主要包含线程池和任务队列)

.线程池管理一池的工作线程(最终数量还得依赖线程池的具体实现)。

.任务队列存放等待被线程池中的空闲线程处理的任务,一旦有后台有新的任务等待空闲线程处理的时候那么空闲线程就类似于”消费者”不断的消费将任务加入到队列的”生产者”。

ThreadPoolExecutor(线程池执行者)

.ThreadPoolExecutor执行一个给定的任务使用一个线程池的线程。
一个典型的初始化例子。

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue
);

参数的含义解释:
1.corePoolSize: 线程池中线程的最小数量,默认情况下线程池中的线程数量为0。随着任务加入队列中,新的线程就会被创建。如果线程池中存在空闲线程但是线程总数小于corePoolSize那么仍然会继续创建新的线程。
2.maximumPoolSize:线程池中允许存在的最大线程总数。如果线程总数>=corePoolSize那么新的线程还会继续被创建直到队列满了。
3.keepAliveTime: 如果线程数大于核心线程数量即corePoolSize时,非核心线程(即额外的空闲线程)将等待新来的任务,如果在我们定义的时间内未能接收到新的任务,那么该线程将被终止。
4.unit: keepAliveTime的时间单位。
5.workQueue: 任务队列,用于存放Runanable任务,它必须是一个BlockingQueue

为什么要在Android或者Java应用中使用Thread Pool Executor

1.Thread Pool Executor本身是一个非常优秀的框架,支持存放任务,取消任务,给任务配置优先级。
2.它减小了所需要创建的线程的最大数量,因为它维护了指定数量的线程在它的池子中,能减少不少线程带来的开支。

在Android中使用ThreadPoolExecutor

首先,创建一个PriorityThreadFactory:

public class PriorityThreadFactory implements ThreadFactory {

    private final int mThreadPriority;

    public PriorityThreadFactory(int threadPriority) {
        mThreadPriority = threadPriority;
    }

    @Override
    public Thread newThread(final Runnable runnable) {
        Runnable wrapperRunnable = new Runnable() {
            @Override
            public void run() {
                try {
                    Process.setThreadPriority(mThreadPriority);
                } catch (Throwable t) {

                }
                runnable.run();
            }
        };
        return new Thread(wrapperRunnable);
    }
}

创建一个MainThreadExecutor:

public class MainThreadExecutor implements Executor {

    private final Handler handler = new Handler(Looper.getMainLooper());

    @Override
    public void execute(Runnable runnable) {
        handler.post(runnable);
    }
}

创建一个DefaultExecutorSupplier:

/*
* 一个executor单例
*/
public class DefaultExecutorSupplier{
    /*
    * 核心线程数量
    */
    public static final int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors();

    /*
    * 后台任务Executor
    */
    private final ThreadPoolExecutor mForBackgroundTasks;
    /*
    * 轻量级后台任务Executor
    */
    private final ThreadPoolExecutor mForLightWeightBackgroundTasks;
    /*
    * 主线程任务Executor
    */
    private final Executor mMainThreadExecutor;
    /*
    * DefaultExecutorSupplier单例对象
    */
    private static DefaultExecutorSupplier sInstance;

    /*
    * 返回一个DefaultExecutorSupplier单例
    */
    public static DefaultExecutorSupplier getInstance() {
       if (sInstance == null) {
         synchronized(DefaultExecutorSupplier.class){                                                                  
             sInstance = new DefaultExecutorSupplier();      
        }
        return sInstance;
    }

    /*
    * DefaultExecutorSupplier构造函数
    */ 
    private DefaultExecutorSupplier() {

        // 设置线程工厂对象
        ThreadFactory backgroundPriorityThreadFactory = new 
                PriorityThreadFactory(Process.THREAD_PRIORITY_BACKGROUND);

        // 初始化mForBackgroundTasks
        mForBackgroundTasks = new ThreadPoolExecutor(
                NUMBER_OF_CORES * 2,
                NUMBER_OF_CORES * 2,
                60L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(),
                backgroundPriorityThreadFactory
        );

        // 初始化mForLightWeightBackgroundTasks
        mForLightWeightBackgroundTasks = new ThreadPoolExecutor(
                NUMBER_OF_CORES * 2,
                NUMBER_OF_CORES * 2,
                60L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(),
                backgroundPriorityThreadFactory
        );

        // 初始化mMainThreadExecutor
        mMainThreadExecutor = new MainThreadExecutor();
    }

    /*
    * 返回后台任务Executor
    */
    public ThreadPoolExecutor forBackgroundTasks() {
        return mForBackgroundTasks;
    }

    /*
    * 返回轻量级的Executor
    */
    public ThreadPoolExecutor forLightWeightBackgroundTasks() {
        return mForLightWeightBackgroundTasks;
    }

    /*
    * 返回主线程Executor
    */
    public Executor forMainThreadTasks() {
        return mMainThreadExecutor;
    }
}

ps:可用线程数量会因不同设备而返回不同的数量。

现在我们就可以在代码中愉快的使用了:

/*
* 用于执行后台任务
*/
public void doSomeBackgroundWork(){
  DefaultExecutorSupplier.getInstance().forBackgroundTasks()
    .execute(new Runnable() {
    @Override
    public void run() {
       // do some background work here.
    }
  });
}

/*
* 用于执行轻量级任务
*/
public void doSomeLightWeightBackgroundWork(){
  DefaultExecutorSupplier.getInstance().forLightWeightBackgroundTasks()
    .execute(new Runnable() {
    @Override
    public void run() {
       // do some light-weight background work here.
    }
  });
}

/*
* 用于执行主线程任务
*/
public void doSomeMainThreadWork(){
  DefaultExecutorSupplier.getInstance().forMainThreadTasks()
    .execute(new Runnable() {
    @Override
    public void run() {
       // do some Main Thread work here.
    }
  });
}

这样,我们就能创建一个线程池用于执行网络任务、I/O任务、繁重的后台任务、等等任务。

如何取消一个任务?

为了取消一个任务,我们必须得到future对象。所以我们需要使用submit来代替execute来提交任务,这样我们就能得到一个future,然后就可以取消一个任务了。

/*
* 得到提交到线程池的future对象
*/
Future future = DefaultExecutorSupplier.getInstance().forBackgroundTasks()
    .submit(new Runnable() {
    @Override
    public void run() {
      // do some background work here.
    }
});

/*
* 取消该任务
*/
future.cancel(true); 

如何为任务设置优先级?

假如我们有20条任务在队列中,但是线程池只有4条线程看用于执行。我们通过优先级来执行任务,毕竟最多只能并发执行4个任务。
再假如我们想把最后加入队列的任务优先执行,那么我们不得不给它设置IMMEDIATE优先级,让他优先执行(因为它的优先级最高)。

为了给任务设置优先级,我们需要重新创建一个Executor:
首先,创建一个优先级ENUM:

/**
 * 优先等级
 */
public enum Priority {
    /**
     * NOTE: 不允许修改这些常量的顺序.
     * 为了确保能按正确的顺序执行.
     */

    /**
     * 低等级. 用于读取数据
     */
    LOW,

    /**
     * 中等级,用于很快就能获取到数据
     */
    MEDIUM,

    /**
     * 高等级. 用于几乎马上就能得到数据
     */
    HIGH,

    /**
     * 高等级,用于能立即得到数据
     */
    IMMEDIATE;

}

创建PriorityRunnable:

public class PriorityRunnable implements Runnable {

    private final Priority priority;

    public PriorityRunnable(Priority priority) {
        this.priority = priority;
    }

    @Override
    public void run() {
      // nothing to do here.
    }

    public Priority getPriority() {
        return priority;
    }

}

创建一个PriorityThreadPoolExecutor extends ThreadPoolExecutor,创建一个PriorityFutureTask implement Comparable< PriorityFutureTask >:

public class PriorityThreadPoolExecutor extends ThreadPoolExecutor {

   public PriorityThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
         TimeUnit unit, ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit,new PriorityBlockingQueue<Runnable>(), threadFactory);
    }

    @Override
    public Future<?> submit(Runnable task) {
        PriorityFutureTask futureTask = new PriorityFutureTask((PriorityRunnable) task);
        execute(futureTask);
        return futureTask;
    }

    private static final class PriorityFutureTask extends FutureTask<PriorityRunnable>
            implements Comparable<PriorityFutureTask> {
        private final PriorityRunnable priorityRunnable;

        public PriorityFutureTask(PriorityRunnable priorityRunnable) {
            super(priorityRunnable, null);
            this.priorityRunnable = priorityRunnable;
        }

        /*
         * compareTo() method is defined in interface java.lang.Comparable and it is used
         * to implement natural sorting on java classes. natural sorting means the the sort 
         * order which naturally applies on object e.g. lexical order for String, numeric 
         * order for Integer or Sorting employee by there ID etc. most of the java core 
         * classes including String and Integer implements CompareTo() method and provide
         * natural sorting.
         */
        @Override
        public int compareTo(PriorityFutureTask other) {
            Priority p1 = priorityRunnable.getPriority();
            Priority p2 = other.priorityRunnable.getPriority();
            return p2.ordinal() - p1.ordinal();
        }
    }
}

最后,在DefaultExecutorSupplier中用PriorityThreadPoolExecutor替换掉ThreadPoolExecutor:

public class DefaultExecutorSupplier{

private final PriorityThreadPoolExecutor mForBackgroundTasks;

private DefaultExecutorSupplier() {

        mForBackgroundTasks = new PriorityThreadPoolExecutor(
                NUMBER_OF_CORES * 2,
                NUMBER_OF_CORES * 2,
                60L,
                TimeUnit.SECONDS,
                backgroundPriorityThreadFactory
        );

    }
}

举个例子,如何设置高等级的任务:

/*
* do some task at high priority
*/
public void doSomeTaskAtHighPriority(){
  DefaultExecutorSupplier.getInstance().forBackgroundTasks()
    .submit(new PriorityRunnable(Priority.HIGH) {
    @Override
    public void run() {
      // do some background work here at high priority.
    }
});
}

这样一个任务就可以优先被执行了。

我希望这些讲解能对你有帮助。

<think>好的,我现在需要帮助用户了解Android中线程池的实现机制,特别是Executor Framework。首先,用户的问题是关于Android线程池的实现方式,提到了Executor Framework,所以我应该重点围绕这个部分展开。 首先,我需要回忆一下Android中线程池的相关知识。记得Android中的线程池主要是通过java.util.concurrent包中的Executor Framework来实现的,这个框架提供了一系列的线程池创建和管理工具。可能涉及到ThreadPoolExecutor这个核心类,以及Executors工厂类提供的几种预定义线程池,比如FixedThreadPool、CachedThreadPool、SingleThreadExecutor等。 接下来,用户给的参考引用中有四个来源,其中引用[1]和[2]提到了使用ExecutorService、AsyncTask和Runnable来实现线程池。而引用[3]和[4]是关于SpringBoot和SpringCloud的,可能和Android无关,但需要确认是否有相关的内容可以借鉴,不过可能用户是误贴了这些内容,或者需要排除干扰。因此,我应该主要关注引用[1]和[2]的内容。 用户的问题还要求回答结构清晰,分步骤说明,并且生成相关问题。同时需要遵循系统级指令中的格式要求,比如数学公式的格式,引用标识的正确使用等。 首先,我应该解释Executor Framework在Android中的实现机制。可能需要分点说明,比如核心组件、线程池类型、任务提交方式、线程池参数等。然后结合代码示例,比如如何使用ExecutorService来创建线程池,执行任务。同时,用户提供的引用中有AsyncTask,虽然现在可能已经被弃用,但可能需要提到,并说明推荐的方式。 然后,需要确保代码示例正确,并且符合用户提供的引用中的方式一,即主类文件使用ExecutorService、AsyncTask、Runnable。但AsyncTask在Android中已经过时,可能需要指出,并建议使用ExecutorService配合Handler或者LiveData来更新UI。 另外,需要检查LaTeX语法是否正确,但用户的问题中可能不涉及数学公式,不过如果有任何公式,比如参数说明中的核心数、队列容量等,可能需要用行内公式格式。 在回答过程中,需要自然地添加引用标识,比如在提到ExecutorService的时候,引用用户提供的引用[1]和[2],但需要确保引用的内容确实相关。例如,引用[1]提到的是Android线程池的经典使用方式,包括ExecutorService、AsyncTask、Runnable,这正好符合用户的问题。 可能需要注意,用户提供的引用[3]和[4]是关于SpringBoot和SpringCloud的,可能与当前问题无关,可以忽略,或者在生成相关问题的时候,如果涉及到其他框架的线程池,可以生成相关问题,但需要明确区分Android和Spring的上下文。 现在,我需要组织回答的结构: 1. 概述Executor Framework在Android中的作用。 2. 核心组件:ThreadPoolExecutor和Executors工厂类。 3. 四种预定义线程池类型及其适用场景。 4. 自定义线程池的参数配置。 5. 结合代码示例说明如何使用ExecutorService提交任务。 6. 提到AsyncTask的过时,推荐使用Executor配合其他机制更新UI。 7. 引用相关站内引用,例如方式一的实现。 同时,生成相关问题,比如线程池参数如何配置、不同线程池的适用场景、AsyncTask的替代方案等。 需要确保回答符合中文,使用正确的术语,避免技术错误,比如不混淆ThreadPoolExecutor和Executors的关系,正确解释各参数的意义。 最后,检查是否符合系统级指令中的格式要求,例如代码块使用正确的语法,引用标识正确放置,没有使用Markdown格式,段落清晰,分点说明等。</think>### Android线程池实现机制(Executor Framework) Android通过Java的`java.util.concurrent`包提供**Executor框架**实现线程池管理,其核心组件是`ThreadPoolExecutor`和`Executors`工厂类。以下为关键实现机制: --- #### 1. **核心组件** - **`ThreadPoolExecutor`** 直接控制线程池参数,包括: - **核心线程数**($corePoolSize$):常驻线程数量 - **最大线程数**($maxPoolSize$):线程池可扩展的最大上限 - **任务队列**($workQueue$):存储待执行任务(如`LinkedBlockingQueue`) - **线程存活时间**($keepAliveTime$):非核心线程空闲时的存活时长[^1] - **`Executors`工厂类** 提供预定义线程池类型,简化创建过程: ```java ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4); // 固定大小线程池 ``` --- #### 2. **Android中的线程池类型** | 类型 | 特点 | 适用场景 | |-----------------------|----------------------------------------------------------------------|------------------------| | **FixedThreadPool** | 固定核心线程数,无超时机制 | CPU密集型任务 | | **CachedThreadPool** | 线程数动态扩展,空闲线程自动回收 | 短期异步任务 | | **SingleThreadPool** | 单一线程顺序执行任务 | 需顺序执行的任务队列 | | **ScheduledThreadPool** | 支持定时或周期性任务 | 定时/延迟任务 | --- #### 3. **任务提交方式** - **`Runnable`接口**:无返回值任务 ```java executorService.execute(new Runnable() { @Override public void run() { // 后台逻辑 } }); ``` - **`Callable`接口**:支持返回结果 ```java Future<String> future = executorService.submit(new Callable<String>() { @Override public String call() throws Exception { return "Result"; } }); ``` --- #### 4. **自定义线程池示例** 通过`ThreadPoolExecutor`配置参数: ```java int corePoolSize = 2; int maxPoolSize = 5; long keepAliveTime = 30L; TimeUnit unit = TimeUnit.SECONDS; BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(10); ThreadPoolExecutor executor = new ThreadPoolExecutor( corePoolSize, maxPoolSize, keepAliveTime, unit, workQueue ); executor.execute(task); // 提交任务 ``` --- #### 5. **与UI线程的交互** - **`AsyncTask`(已过时)**:早期用于后台任务与UI更新,但易引发内存泄漏[^2]。 - **推荐方式**:使用`ExecutorService`配合`Handler`或`LiveData`更新UI: ```java executor.execute(() -> { // 后台计算 String result = processData(); new Handler(Looper.getMainLooper()).post(() -> { textView.setText(result); // 更新UI }); }); ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值