使用 ThreadPoolExecutor 实现任务暂停

在现代 Android 开发中,多线程是一项重要的技术,帮助我们更高效地执行任务。ThreadPoolExecutor 是 Java 提供的一种强大工具,可以用于管理线程池。在某些情况下,我们可能需要暂停所有任务的执行。本文将引导你完成这个过程,步骤明确,代码清晰,助你轻松上手。

流程概述

为了实现“暂停所有任务”,我们需要经过以下几个步骤:

步骤 内容 说明
步骤 1 创建自定义的 ThreadPoolExecutor 继承 ThreadPoolExecutor 并添加暂停功能
步骤 2 实现暂停逻辑 使用synchronized锁机制来实现暂停功能
步骤 3 提供操作方法 提供方法以便启动、暂停、恢复线程
步骤 4 测试代码 编写测试用例来验证我们的实现

接下来,我们会详细介绍每一个步骤及其实现代码。

步骤 1:创建自定义的 ThreadPoolExecutor

首先,我们需要创建一个自定义的 ThreadPoolExecutor,以便能够扩展其功能。

import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import android.util.Log;

public class PausableThreadPoolExecutor extends ThreadPoolExecutor {
    private boolean isPaused;

    public PausableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, new LinkedBlockingQueue<Runnable>());
        isPaused = false;
    }

    // 暂停线程池
    public synchronized void pause() {
        isPaused = true;
    }

    // 恢复线程池
    public synchronized void resume() {
        isPaused = false;
        notifyAll();  // 唤醒所有等待的线程
    }

    // 重写 beforeExecute 方法,用于暂停逻辑
    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        super.beforeExecute(t, r);
        synchronized (this) {
            while (isPaused) {
                try {
                    wait(); // 如果线程池处于暂停状态,当前线程将等待
                } catch (InterruptedException e) {
                    Log.e("PausableThreadPoolExecutor", "Thread interrupted", e);
                }
            }
        }
    }
}

代码说明

  • PausableThreadPoolExecutor 继承自 ThreadPoolExecutor,并添加了 isPaused 变量用于跟踪线程池是否被暂停。
  • pause() 方法会将 isPaused 设置为 true,并且保持同步,以确保安全性。
  • resume() 方法将 isPaused 设置为 false,并使用 notifyAll() 唤醒所有等待的线程。
  • beforeExecute(Thread t, Runnable r) 方法是重写的,用于在每个线程开始执行之前检查是否需要暂停。

步骤 2:实现暂停逻辑

在我们已经创建的自定义线程池基础上,我们需要进一步实现暂停的具体逻辑。

在上面的代码中,我们已经使用了 wait() 方法来实现暂停。它在 beforeExecute() 方法中检查线程池的状态,若处于暂停状态,会使当前调用线程挂起,直到被唤醒。

步骤 3:提供操作方法

现在我们已经有了基本的线程池。接下来需要提供一些方便用户操作的方法。

public void testPausableThreadPool() {
    PausableThreadPoolExecutor executor = new PausableThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS);
    
    // 提交任务
    for (int i = 0; i < 10; i++) {
        int taskId = i;
        executor.execute(() -> {
            try {
                Thread.sleep(1000); // 模拟任务执行时间
                Log.d("Task", "Task " + taskId + " executed");
            } catch (InterruptedException e) {
                Log.e("Task", "Task interrupted", e);
            }
        });
    }

    executor.pause(); // 暂停任务

    // 恢复任务
    executor.resume(); // 恢复任务执行
}

代码说明

  • testPausableThreadPool 方法中,我们创建了一个 PausableThreadPoolExecutor 实例。
  • 用一个循环提交了 10 个任务,模拟每个任务执行1秒。
  • 首先暂停任务,然后再调用恢复方法。

步骤 4:测试代码

最后一步是测试我们的实现。可以调用不同的操作来确认是否如预期一样工作。将上述的 testPausableThreadPool 方法放在你的活动或 Fragment 中的合适位置,确保它能被调用。

结尾

通过自定义 ThreadPoolExecutor,我们实现了任务的暂停和恢复功能。上面提供的代码和步骤希望能让你在 Android 开发中更有效地控制线程操作。掌握了这个技术,你就能更好地管理长时间运行的任务,也能在合适的时候暂停它们,从而提升用户体验。

如果你在实际使用中有任何疑问,或者想进一步了解线程池的其它功能,随时查阅相关文档或咨询更多的开发者。继续探索,你会在多线程编程中找到更多的乐趣和可能性!

图示任务和线程池分配情况如下:

pie
    title 线程池使用情况
    "执行中": 70
    "暂停": 30

希望这些内容能够帮助你更好地理解和实现线程池的暂停功能。如果有更多问题,欢迎随时交流!