线程池

线程池是现代并发编程的基石 ,是Android中处理异步任务的工业级解决方案。线程池提供了更灵活、更高效的并发控制能力。

为什么需要线程池

java 复制代码
// 问题代码:频繁创建销毁线程
public class NaiveThreadManager {
    public void processTasks(List<Runnable> tasks) {
        for (Runnable task : tasks) {
            // 为每个任务创建新线程 ❌
            new Thread(task).start();
            
            // 如果有1000个任务,就会创建1000个线程!
            // 这会导致:
            // 1. 内存消耗大(每个线程需要1MB+栈内存)
            // 2. CPU调度开销大(线程上下文切换)
            // 3. 系统不稳定(可能超出系统线程限制)
        }
    }
}

线程创建的成本(以典型的Android设备为例):

成本类型 具体开销
内存开销 每个线程约1MB栈内存(可设置)
创建时间 约1-5毫秒(包括系统调用、内存分配)
销毁时间 约0.5-2毫秒
调度开销 线程切换需要保存/恢复寄存器、内存页表等

线程池的解决方案

java 复制代码
// 使用线程池
public class ThreadPoolManager {
    private ExecutorService executor;
    
    public ThreadPoolManager() {
        // 创建固定大小的线程池
        executor = Executors.newFixedThreadPool(4); // 只有4个线程
    }
    
    public void processTasks(List<Runnable> tasks) {
        for (Runnable task : tasks) {
            executor.execute(task); // 重用已有的线程
        }
    }
}

线程池的核心价值

  1. 线程复用:减少创建/销毁开销
  2. 资源控制:限制并发线程数量
  3. 任务管理:提供队列、拒绝策略等
  4. 监控统计:可获取任务完成情况

ThreadPoolExecutor的核心架构

七个核心参数

java 复制代码
public ThreadPoolExecutor(
    int corePoolSize,              // 核心线程数
    int maximumPoolSize,           // 最大线程数
    long keepAliveTime,            // 空闲线程存活时间
    TimeUnit unit,                 // 时间单位
    BlockingQueue<Runnable> workQueue,  // 任务队列
    ThreadFactory threadFactory,   // 线程工厂
    RejectedExecutionHandler handler    // 拒绝策略
) { /* 实现 */ }

corePoolSize(核心线程数)

java 复制代码
// 核心线程的特点:
// 1. 默认情况下,核心线程会一直存活(即使空闲)
// 2. 可以通过allowCoreThreadTimeOut(true)让核心线程超时终止
// 3. 线程池刚创建时,核心线程数为0(懒加载)

// Android中常见的核心线程数配置:
int availableProcessors = Runtime.getRuntime().availableProcessors();
int corePoolSize = Math.max(2, Math.min(availableProcessors - 1, 4));
// 通常取CPU核心数-1,范围在2-4之间

maximumPoolSize(最大线程数)

java 复制代码
// 最大线程数限制:
// 1. 当任务队列满了,且当前线程数 < maximumPoolSize时,创建新线程
// 2. 创建的是"非核心线程"(救急线程)
// 3. 非核心线程空闲超过keepAliveTime会被回收

// 常见配置:
int maximumPoolSize = availableProcessors * 2 + 1;
// 公式:CPU核心数 × 2 + 1(考虑了超线程和I/O等待)

keepAliveTime(空闲线程存活时间)

java 复制代码
// 只对非核心线程有效(除非设置了allowCoreThreadTimeOut)
long keepAliveTime = 30L;  // 30秒
TimeUnit unit = TimeUnit.SECONDS;

// Android中的典型值:
// - CPU密集型任务:60-120秒
// - I/O密集型任务:10-30秒
// - 混合型任务:30-60秒

workQueue(任务队列)

java 复制代码
// 常见的任务队列类型:
BlockingQueue<Runnable> queue;

// 1. SynchronousQueue(直接传递队列)
queue = new SynchronousQueue<>();
// 特点:不存储元素,每个插入操作必须等待一个移除操作
// 适用场景:线程数无限制,快速处理短任务

// 2. LinkedBlockingQueue(无界队列)
queue = new LinkedBlockingQueue<>();
// 特点:默认Integer.MAX_VALUE容量,可能导致内存溢出
// 适用场景:任务量不可控,但需要保证所有任务都被执行

// 3. ArrayBlockingQueue(有界队列)
queue = new ArrayBlockingQueue<>(100);
// 特点:固定容量,公平性可配置
// 适用场景:需要控制队列长度,防止资源耗尽

// 4. PriorityBlockingQueue(优先级队列)
queue = new PriorityBlockingQueue<>(11, Comparator.comparing(Task::getPriority));
// 特点:按优先级排序,可实现任务优先级调度
// 适用场景:需要区分任务优先级的场景

threadFactory(线程工厂)

java 复制代码
ThreadFactory factory = new ThreadFactory() {
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix = "MyThreadPool-";
    
    @Override
    public Thread newThread(Runnable r) {
        // 自定义线程属性
        Thread t = new Thread(r, namePrefix + threadNumber.getAndIncrement());
        
        // 设置线程优先级
        if (t.isDaemon()) {
            t.setDaemon(false);  // 默认为非守护线程
        }
        t.setPriority(Thread.NORM_PRIORITY);  // 正常优先级
        
        // 设置未捕获异常处理器
        t.setUncaughtExceptionHandler((thread, throwable) -> {
            Log.e("ThreadPool", "线程" + thread.getName() + "异常: " + throwable.getMessage());
        });
        
        return t;
    }
};

handler(拒绝策略)

java 复制代码
// 当线程池已关闭或队列已满时的处理策略

// 1. AbortPolicy(默认):抛出RejectedExecutionException
RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();

// 2. CallerRunsPolicy:由调用者线程执行任务
handler = new ThreadPoolExecutor.CallerRunsPolicy();
// 特点:不会丢弃任务,但可能阻塞调用者线程

// 3. DiscardPolicy:直接丢弃任务,不抛异常
handler = new ThreadPoolExecutor.DiscardPolicy();

// 4. DiscardOldestPolicy:丢弃队列中最旧的任务,然后重试
handler = new ThreadPoolExecutor.DiscardOldestPolicy();

// 5. 自定义策略
handler = (runnable, executor) -> {
    // 记录日志
    Log.w("ThreadPool", "任务被拒绝,保存到数据库等待重试");
    
    // 将任务保存到数据库
    saveTaskToDatabase(runnable);
    
    // 或者尝试重新提交
    try {
        executor.getQueue().put(runnable);  // 阻塞式插入
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
};

线程池状态机

java 复制代码
// ThreadPoolExecutor的内部状态
private static final int RUNNING    = -1 << COUNT_BITS;  // 运行中
private static final int SHUTDOWN   =  0 << COUNT_BITS;  // 关闭中(不接受新任务)
private static final int STOP       =  1 << COUNT_BITS;  // 停止(中断所有线程)
private static final int TIDYING    =  2 << COUNT_BITS;  // 整理中(所有任务终止)
private static final int TERMINATED =  3 << COUNT_BITS;  // 已终止

// 状态转换:
// RUNNING → SHUTDOWN: 调用shutdown()
// RUNNING/SHUTDOWN → STOP: 调用shutdownNow()
// STOP → TIDYING: 所有工作线程终止
// SHUTDOWN → TIDYING: 队列为空且所有工作线程终止
// TIDYING → TERMINATED: terminated()钩子执行完成

线程池的工作流程

任务执行流程图

execute()方法源码解析

java 复制代码
public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    
    int c = ctl.get();  // ctl包含线程池状态和线程数量
    
    // 阶段1:当前线程数 < corePoolSize
    if (workerCountOf(c) < corePoolSize) {
        if (addWorker(command, true))  // 创建核心线程
            return;
        c = ctl.get();
    }
    
    // 阶段2:线程数已达核心数,尝试加入队列
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        // 双重检查:如果线程池已关闭,则移除任务并拒绝
        if (!isRunning(recheck) && remove(command))
            reject(command);
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false);  // 保证至少有一个线程
    }
    
    // 阶段3:队列已满,尝试创建非核心线程
    else if (!addWorker(command, false))
        // 阶段4:线程数已达maximumPoolSize,执行拒绝策略
        reject(command);
}
  • 优先级:核心线程 > 任务队列 > 非核心线程 > 拒绝策略

  • 懒加载:线程不是预先创建的,而是有任务时才创建

  • 双重检查:加入队列后再次检查线程池状态

addWroker()方法解析

java 复制代码
private boolean addWorker(Runnable firstTask, boolean core) {
    retry:
    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c);
        
        // 检查线程池状态
        if (rs >= SHUTDOWN &&
            !(rs == SHUTDOWN && firstTask == null && !workQueue.isEmpty()))
            return false;
        
        for (;;) {
            int wc = workerCountOf(c);
            // 检查线程数量限制
            if (wc >= CAPACITY ||
                wc >= (core ? corePoolSize : maximumPoolSize))
                return false;
            
            // 使用CAS增加线程计数
            if (compareAndIncrementWorkerCount(c))
                break retry;  // 计数增加成功,跳出循环
            
            c = ctl.get();
            if (runStateOf(c) != rs)
                continue retry;
        }
    }
    
    // 创建Worker(内部类,封装了线程和任务)
    Worker w = null;
    try {
        w = new Worker(firstTask);
        final Thread t = w.thread;
        if (t != null) {
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                // 再次检查状态
                int rs = runStateOf(ctl.get());
                if (rs < SHUTDOWN ||
                    (rs == SHUTDOWN && firstTask == null)) {
                    if (t.isAlive())  // 线程已启动
                        throw new IllegalThreadStateException();
                    
                    // 添加到workers集合
                    workers.add(w);
                    int s = workers.size();
                    if (s > largestPoolSize)
                        largestPoolSize = s;
                }
            } finally {
                mainLock.unlock();
            }
            
            // 启动线程
            if (t != null) {
                t.start();
                workerStarted = true;
            }
        }
    } finally {
        if (!workerStarted)
            addWorkerFailed(w);
    }
    return workerStarted;
}

Worker类的内部机制

java 复制代码
private final class Worker
    extends AbstractQueuedSynchronizer
    implements Runnable {
    
    final Thread thread;      // 实际执行的线程
    Runnable firstTask;       // 初始任务(可能为null)
    volatile long completedTasks;  // 完成的任务数
    
    Worker(Runnable firstTask) {
        setState(-1);  // 初始状态,禁止中断
        this.firstTask = firstTask;
        this.thread = getThreadFactory().newThread(this);
    }
    
    public void run() {
        runWorker(this);
    }
    
    // 其他方法:锁状态管理、中断控制等
}

Worker的关键作用

  1. 封装线程和任务
  2. 实现AQS锁:用于控制线程中断
  3. 统计完成任务数

Android中的线程池实践

AsyncTask的内部线程池配置

java 复制代码
// AsyncTask的线程池配置
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE_SECONDS = 30;

public static final Executor THREAD_POOL_EXECUTOR;

static {
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
            CORE_POOL_SIZE,       // 核心线程数:2-4
            MAXIMUM_POOL_SIZE,    // 最大线程数:CPU×2+1
            KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
            new LinkedBlockingQueue<Runnable>(128),  // 队列容量128
            sThreadFactory
    );
    
    threadPoolExecutor.allowCoreThreadTimeOut(true);  // 核心线程也会超时
    THREAD_POOL_EXECUTOR = threadPoolExecutor;
}

设计分析

  1. 核心线程数保守:2-4个,避免过多线程竞争CPU
  2. 队列容量有限:128,防止无限制积压
  3. 核心线程可超时:长时间空闲时释放资源
  4. 适合场景:短时、轻量的异步任务

不同任务类型的线程池配置

场景1:CPU密集型任务(如图像处理、计算)

java 复制代码
public class CpuIntensiveThreadPool {
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    
    // CPU密集型:线程数 ≈ CPU核心数
    private static final int CORE_POOL_SIZE = CPU_COUNT;
    private static final int MAX_POOL_SIZE = CPU_COUNT * 2;  // 预留一些应对突发
    
    // 使用有界队列,防止内存溢出
    private static final BlockingQueue<Runnable> WORK_QUEUE = 
        new ArrayBlockingQueue<>(128);
    
    // 线程存活时间较长,避免频繁创建
    private static final long KEEP_ALIVE_TIME = 60L;
    
    private final ThreadPoolExecutor executor;
    
    public CpuIntensiveThreadPool() {
        executor = new ThreadPoolExecutor(
            CORE_POOL_SIZE,
            MAX_POOL_SIZE,
            KEEP_ALIVE_TIME, TimeUnit.SECONDS,
            WORK_QUEUE,
            new CustomThreadFactory("CPU-Intensive"),
            new ThreadPoolExecutor.CallerRunsPolicy()  // 饱和时让调用者执行
        );
        
        // 预热核心线程
        executor.prestartAllCoreThreads();
    }
}

场景2:I/O密集型任务(如网络请求、文件读写)

java 复制代码
public class IoIntensiveThreadPool {
    // I/O密集型:可以创建较多线程
    // 因为线程大部分时间在等待I/O,不会占用CPU
    private static final int CORE_POOL_SIZE = 4;  // 基础线程数
    private static final int MAX_POOL_SIZE = 20;  // 最大线程数
    
    // 使用同步队列,确保快速响应
    private static final BlockingQueue<Runnable> WORK_QUEUE = 
        new SynchronousQueue<>();
    
    // 线程存活时间较短,及时回收
    private static final long KEEP_ALIVE_TIME = 10L;
    
    private final ThreadPoolExecutor executor;
    
    public IoIntensiveThreadPool() {
        executor = new ThreadPoolExecutor(
            CORE_POOL_SIZE,
            MAX_POOL_SIZE,
            KEEP_ALIVE_TIME, TimeUnit.SECONDS,
            WORK_QUEUE,
            new CustomThreadFactory("IO-Intensive"),
            new ThreadPoolExecutor.AbortPolicy()  // 饱和时快速失败
        );
    }
}

场景3:混合型任务

java 复制代码
public class HybridThreadPool {
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    
    // 混合型:根据任务类型动态调整
    private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
    private static final int MAX_POOL_SIZE = CPU_COUNT * 3;
    
    // 使用优先级队列,区分任务优先级
    private static final BlockingQueue<Runnable> WORK_QUEUE = 
        new PriorityBlockingQueue<>(256, Comparator.comparingInt(
            task -> ((PrioritizedTask) task).getPriority()
        ));
    
    private final ThreadPoolExecutor executor;
    
    public HybridThreadPool() {
        executor = new ThreadPoolExecutor(
            CORE_POOL_SIZE,
            MAX_POOL_SIZE,
            30L, TimeUnit.SECONDS,
            WORK_QUEUE,
            new CustomThreadFactory("Hybrid"),
            new CustomRejectionHandler()  // 自定义拒绝策略
        );
        
        // 监控线程池状态
        startMonitor();
    }
    
    // 优先级任务
    static class PrioritizedTask implements Runnable {
        private final int priority;  // 数字越小优先级越高
        private final Runnable task;
        
        PrioritizedTask(int priority, Runnable task) {
            this.priority = priority;
            this.task = task;
        }
        
        int getPriority() { return priority; }
        
        @Override
        public void run() { task.run(); }
    }
}

Executors工厂类的四种线程池

java 复制代码
// 只需知道这四种类型及其特点
public class ExecutorsExample {
    
    // 1. FixedThreadPool(固定大小线程池)
    public void fixedThreadPoolExample() {
        ExecutorService fixedPool = Executors.newFixedThreadPool(5);
        // 特点:
        // - 核心线程数 = 最大线程数 = nThreads
        // - 使用无界队列(LinkedBlockingQueue)
        // - 适合负载较重的服务器,需要限制线程数量
        // 风险:任务可能无限堆积,导致OOM
    }
    
    // 2. CachedThreadPool(缓存线程池)
    public void cachedThreadPoolExample() {
        ExecutorService cachedPool = Executors.newCachedThreadPool();
        // 特点:
        // - 核心线程数 = 0,最大线程数 = Integer.MAX_VALUE
        // - 使用同步队列(SynchronousQueue)
        // - 线程空闲60秒后回收
        // - 适合大量短时异步任务
        // 风险:可能创建过多线程,导致OOM
    }
    
    // 3. SingleThreadExecutor(单线程线程池)
    public void singleThreadExecutorExample() {
        ExecutorService singlePool = Executors.newSingleThreadExecutor();
        // 特点:
        // - 只有一个线程,保证任务顺序执行
        // - 使用无界队列
        // - 适合需要保证顺序的任务
        // 风险:HandlerThread的线程池版本,但更灵活
    }
    
    // 4. ScheduledThreadPool(定时线程池)
    public void scheduledThreadPoolExample() {
        ScheduledExecutorService scheduledPool = 
            Executors.newScheduledThreadPool(3);
        // 特点:
        // - 可以定时执行、延迟执行、周期性执行
        // - 核心线程数可配置,最大线程数 = Integer.MAX_VALUE
        // - 使用DelayedWorkQueue(延迟队列)
    }
}

Executors创建的线程池在Android中不推荐使用,因为它们:

  1. 使用无界队列,可能造成OOM
  2. 默认配置不适合移动设备
  3. 缺乏监控和调优能力

线程池的高级特性

监控与统计

java 复制代码
public class MonitorableThreadPool extends ThreadPoolExecutor {
    
    public MonitorableThreadPool(
            int corePoolSize,
            int maximumPoolSize,
            long keepAliveTime,
            TimeUnit unit,
            BlockingQueue<Runnable> workQueue,
            ThreadFactory threadFactory,
            RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, 
              workQueue, threadFactory, handler);
    }
    
    // 监控指标
    private final AtomicLong totalTasks = new AtomicLong(0);
    private final AtomicLong completedTasks = new AtomicLong(0);
    private final AtomicLong failedTasks = new AtomicLong(0);
    private final AtomicLong totalQueueTime = new AtomicLong(0);
    
    @Override
    public void execute(Runnable command) {
        long submitTime = System.currentTimeMillis();
        
        super.execute(() -> {
            long queueTime = System.currentTimeMillis() - submitTime;
            totalQueueTime.addAndGet(queueTime);
            totalTasks.incrementAndGet();
            
            try {
                command.run();
                completedTasks.incrementAndGet();
            } catch (Exception e) {
                failedTasks.incrementAndGet();
                throw e;
            }
        });
    }
    
    // 获取监控数据
    public ThreadPoolStats getStats() {
        ThreadPoolStats stats = new ThreadPoolStats();
        stats.setPoolSize(this.getPoolSize());
        stats.setActiveCount(this.getActiveCount());
        stats.setCorePoolSize(this.getCorePoolSize());
        stats.setMaximumPoolSize(this.getMaximumPoolSize());
        stats.setLargestPoolSize(this.getLargestPoolSize());
        stats.setTaskCount(this.getTaskCount());
        stats.setCompletedTaskCount(this.getCompletedTaskCount());
        stats.setQueueSize(this.getQueue().size());
        
        // 自定义指标
        stats.setTotalTasks(totalTasks.get());
        stats.setCompletedTasks(completedTasks.get());
        stats.setFailedTasks(failedTasks.get());
        if (totalTasks.get() > 0) {
            stats.setAvgQueueTime(totalQueueTime.get() / totalTasks.get());
        }
        
        return stats;
    }
    
    public static class ThreadPoolStats {
        private int poolSize;           // 当前线程数
        private int activeCount;        // 活动线程数
        private int corePoolSize;       // 核心线程数
        private int maximumPoolSize;    // 最大线程数
        private int largestPoolSize;    // 历史最大线程数
        private long taskCount;         // 总任务数
        private long completedTaskCount;// 已完成任务数
        private int queueSize;          // 队列大小
        private long totalTasks;        // 自定义:总任务数
        private long completedTasks;    // 自定义:已完成数
        private long failedTasks;       // 自定义:失败数
        private long avgQueueTime;      // 自定义:平均排队时间
        
        // getters and setters
    }
}

线程池的动态调整

java 复制代码
public class DynamicThreadPool {
    private ThreadPoolExecutor executor;
    
    public DynamicThreadPool() {
        executor = new ThreadPoolExecutor(
            2,  // 初始核心线程数
            10, // 初始最大线程数
            60, TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(100)
        );
    }
    
    // 动态调整核心线程数
    public void setCorePoolSize(int newCoreSize) {
        int oldCoreSize = executor.getCorePoolSize();
        
        if (newCoreSize < oldCoreSize) {
            // 减少核心线程数
            executor.setCorePoolSize(newCoreSize);
        } else if (newCoreSize > oldCoreSize) {
            // 增加核心线程数
            executor.setCorePoolSize(newCoreSize);
            
            // 如果当前线程数 < 新核心数,创建新线程
            if (executor.getPoolSize() < newCoreSize) {
                int threadsToStart = newCoreSize - executor.getPoolSize();
                for (int i = 0; i < threadsToStart; i++) {
                    executor.execute(() -> {
                        // 空任务,只是为了创建线程
                    });
                }
            }
        }
    }
    
    // 动态调整最大线程数
    public void setMaximumPoolSize(int newMaxSize) {
        executor.setMaximumPoolSize(newMaxSize);
    }
    
    // 根据负载自动调整
    public void autoAdjust() {
        ThreadPoolExecutor executor = this.executor;
        
        // 监控指标
        int activeCount = executor.getActiveCount();
        int poolSize = executor.getPoolSize();
        int queueSize = executor.getQueue().size();
        
        // 调整策略
        if (queueSize > 50 && activeCount == poolSize) {
            // 队列积压严重,且所有线程都在忙碌
            int newCoreSize = Math.min(poolSize + 2, executor.getMaximumPoolSize());
            setCorePoolSize(newCoreSize);
            
            Log.d("DynamicThreadPool", 
                "增加核心线程数: " + poolSize + " -> " + newCoreSize +
                " (队列大小: " + queueSize + ")");
        } 
        else if (queueSize < 10 && poolSize > executor.getCorePoolSize()) {
            // 队列空闲,且有超出核心的线程
            // 这些线程会在keepAliveTime后自动回收
            Log.d("DynamicThreadPool", 
                "队列空闲,非核心线程将在空闲时回收");
        }
    }
}

任务优先级与调度

java 复制代码
public class PriorityThreadPool {
    
    static class PriorityFutureTask extends FutureTask<Void> 
                                   implements Comparable<PriorityFutureTask> {
        private final int priority;
        
        public PriorityFutureTask(Runnable runnable, int priority) {
            super(runnable, null);
            this.priority = priority;
        }
        
        @Override
        public int compareTo(PriorityFutureTask other) {
            // 优先级数字越小,优先级越高
            return Integer.compare(this.priority, other.priority);
        }
    }
    
    private final ThreadPoolExecutor executor;
    private final PriorityBlockingQueue<Runnable> queue;
    
    public PriorityThreadPool(int corePoolSize, int maxPoolSize) {
        queue = new PriorityBlockingQueue<>();
        
        executor = new ThreadPoolExecutor(
            corePoolSize,
            maxPoolSize,
            60L, TimeUnit.SECONDS,
            queue,
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy()
        ) {
            @Override
            protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
                if (runnable instanceof PrioritizedRunnable) {
                    PrioritizedRunnable pr = (PrioritizedRunnable) runnable;
                    return (RunnableFuture<T>) new PriorityFutureTask(runnable, pr.getPriority());
                }
                return super.newTaskFor(runnable, value);
            }
        };
    }
    
    public void submit(PrioritizedRunnable task) {
        executor.execute(task);
    }
    
    public interface PrioritizedRunnable extends Runnable {
        int getPriority();  // 0:最高, 1:高, 2:中, 3:低, 4:最低
    }
    
    // 使用示例
    public void example() {
        submit(() -> {
            Log.d("Priority", "执行高优先级任务");
        }, 1);  // 高优先级
        
        submit(() -> {
            Log.d("Priority", "执行低优先级任务");
        }, 4);  // 低优先级
    }
}

线程池的常见陷阱

内存泄漏:线程持有Context引用

java 复制代码
// ❌ 错误示例:线程持有了Activity引用
public class LeakyThreadPool {
    private final ExecutorService executor = Executors.newFixedThreadPool(2);
    private Activity leakyActivity;
    
    public void setActivity(Activity activity) {
        this.leakyActivity = activity;
    }
    
    public void submitTask() {
        executor.execute(() -> {
            // 持有了Activity引用
            SystemClock.sleep(30000);  // 30秒
            
            if (leakyActivity != null && !leakyActivity.isFinishing()) {
                leakyActivity.runOnUiThread(() -> {
                    // 更新UI
                });
            }
        });
    }
}

// ✅ 正确示例:使用弱引用
public class SafeThreadPool {
    private final ExecutorService executor = Executors.newFixedThreadPool(2);
    private WeakReference<Activity> activityRef;
    
    public void setActivity(Activity activity) {
        this.activityRef = new WeakReference<>(activity);
    }
    
    public void submitTask() {
        executor.execute(() -> {
            SystemClock.sleep(30000);
            
            Activity activity = activityRef != null ? activityRef.get() : null;
            if (activity != null && !activity.isFinishing()) {
                // 使用Application Context或者检查生命周期
                activity.runOnUiThread(() -> {
                    // 更新UI
                });
            }
        });
    }
    
    public void shutdown() {
        executor.shutdown();
        try {
            if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
                executor.shutdownNow();
            }
        } catch (InterruptedException e) {
            executor.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
}

任务饥饿:错误配置导致某些任务永远得不到执行

java 复制代码
public class StarvationExample {
    
    public void demonstrateStarvation() {
        // 错误配置:单线程 + 无界队列
        ExecutorService executor = Executors.newSingleThreadExecutor();
        
        // 提交一个长时间运行的任务
        executor.submit(() -> {
            SystemClock.sleep(10000);  // 运行10秒
            Log.d("Starvation", "长时间任务完成");
        });
        
        // 提交多个短任务
        for (int i = 0; i < 10; i++) {
            final int taskId = i;
            executor.submit(() -> {
                Log.d("Starvation", "短任务 " + taskId + " 开始");
                SystemClock.sleep(100);
                Log.d("Starvation", "短任务 " + taskId + " 完成");
            });
        }
        
        // 问题:短任务需要等待10秒才能开始执行!
        // 这就是"任务饥饿"现象
    }
    
    // 解决方案:使用合适的线程池配置
    public void solution() {
        // 方案1:使用多线程
        ExecutorService executor = Executors.newFixedThreadPool(3);
        
        // 方案2:使用优先级队列
        ThreadPoolExecutor priorityExecutor = new ThreadPoolExecutor(
            2, 4, 60, TimeUnit.SECONDS,
            new PriorityBlockingQueue<>()
        );
        
        // 方案3:使用ScheduledExecutorService处理定时任务
        ScheduledExecutorService scheduledExecutor = 
            Executors.newScheduledThreadPool(2);
    }
}

线程泄露:忘记关闭线程池

java 复制代码
public class ThreadLeakExample {
    private ExecutorService executor;
    
    public void start() {
        executor = Executors.newFixedThreadPool(2);
        
        // 提交任务...
        executor.submit(() -> {
            // 长时间运行的任务
        });
    }
    
    // ❌ 忘记关闭线程池
    // 即使Activity销毁,线程池中的线程依然存在
    // 它们持有ThreadLeakExample的引用,导致内存泄漏
    
    // ✅ 正确做法
    public void cleanup() {
        if (executor != null) {
            // 优雅关闭
            executor.shutdown();
            try {
                // 等待现有任务完成
                if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
                    // 强制关闭
                    executor.shutdownNow();
                }
            } catch (InterruptedException e) {
                executor.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }
}

Android中的最佳实践

根据设备性能动态配置

java 复制代码
public class AdaptiveThreadPool {
    
    public static ExecutorService createOptimizedThreadPool() {
        // 获取设备信息
        int cpuCount = Runtime.getRuntime().availableProcessors();
        long totalMemory = Runtime.getRuntime().totalMemory();
        long maxMemory = Runtime.getRuntime().maxMemory();
        
        // 低端设备配置
        if (totalMemory < 2 * 1024 * 1024 * 1024L) {  // 小于2GB
            return createThreadPoolForLowEndDevice(cpuCount);
        } 
        // 高端设备配置
        else {
            return createThreadPoolForHighEndDevice(cpuCount);
        }
    }
    
    private static ExecutorService createThreadPoolForLowEndDevice(int cpuCount) {
        // 保守配置
        int corePoolSize = Math.max(1, cpuCount - 1);
        int maxPoolSize = Math.min(cpuCount * 2, 8);  // 最大8个线程
        
        return new ThreadPoolExecutor(
            corePoolSize,
            maxPoolSize,
            30L, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(64),  // 有界队列
            new CustomThreadFactory("LowEnd"),
            new ThreadPoolExecutor.DiscardOldestPolicy()  // 丢弃旧任务
        );
    }
    
    private static ExecutorService createThreadPoolForHighEndDevice(int cpuCount) {
        // 激进配置
        int corePoolSize = cpuCount;
        int maxPoolSize = cpuCount * 4;
        
        return new ThreadPoolExecutor(
            corePoolSize,
            maxPoolSize,
            60L, TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(256),
            new CustomThreadFactory("HighEnd"),
            new ThreadPoolExecutor.CallerRunsPolicy()  // 调用者执行
        );
    }
}

问题解析

Q1:ThreadPoolExecutor的各个参数有什么作用?

A

  1. corePoolSize:核心线程数,即使空闲也会保留的线程数量
  2. maximumPoolSize:最大线程数,包括核心线程和非核心线程
  3. keepAliveTime:非核心线程的空闲存活时间
  4. unit:keepAliveTime的时间单位
  5. workQueue:任务队列,用于保存等待执行的任务
  6. threadFactory:创建新线程的工厂
  7. handler:拒绝策略,当线程池饱和时的处理方式

Q2:线程池的任务执行流程是怎样的?

A

  1. 提交任务时,如果当前线程数 < corePoolSize,创建核心线程执行
  2. 如果线程数 ≥ corePoolSize,尝试将任务加入队列
  3. 如果队列已满,且线程数 < maximumPoolSize,创建非核心线程执行
  4. 如果队列已满,且线程数 ≥ maximumPoolSize,执行拒绝策略

简单记忆:核心线程 → 队列 → 非核心线程 → 拒绝

Q3:常用的阻塞队列有哪些?各有什么特点?

A

  1. SynchronousQueue:不存储元素,每个插入必须等待一个移除
  2. LinkedBlockingQueue:基于链表的无界队列(默认Integer.MAX_VALUE)
  3. ArrayBlockingQueue:基于数组的有界队列
  4. PriorityBlockingQueue:支持优先级的无界队列
  5. DelayedWorkQueue:延迟队列,用于ScheduledThreadPool

Q4:线程池的拒绝策略有哪些?

A

  1. AbortPolicy:默认策略,抛出RejectedExecutionException
  2. CallerRunsPolicy:用调用者线程执行任务
  3. DiscardPolicy:直接丢弃任务,不抛异常
  4. DiscardOldestPolicy:丢弃队列中最旧的任务,然后重试
  5. 自定义策略:实现RejectedExecutionHandler接口

Q5:如何合理配置线程池参数?

A:根据任务类型:

  1. CPU密集型:线程数 ≈ CPU核心数,避免过多线程上下文切换
  2. I/O密集型:线程数可以多一些,因为线程大部分时间在等待
  3. 混合型:根据具体情况调整,可监控线程利用率动态调整

经验公式

  • CPU密集型:Ncpu + 1

  • I/O密集型:Ncpu × 2

  • 最佳线程数 = Ncpu × Ucpu × (1 + W/C)

    • Ncpu: CPU核心数
    • Ucpu: 目标CPU利用率(0~1)
    • W/C: 等待时间/计算时间

Q6:线程池有哪些状态?如何转换?

A

  1. RUNNING:接收新任务,处理队列任务
  2. SHUTDOWN:不接收新任务,但处理队列任务
  3. STOP:不接收新任务,不处理队列任务,中断正在执行的任务
  4. TIDYING:所有任务已终止,workerCount为0
  5. TERMINATED:terminated()方法执行完成

转换:RUNNING → shutdown() → SHUTDOWN → 队列空且线程终止 → TIDYING → terminated() → TERMINATED

Q7:execute()和submit()有什么区别?

A

  1. execute() :提交Runnable任务,无返回值

  2. submit() :可以提交Runnable或Callable任务,返回Future对象

    • 可以获取任务执行结果
    • 可以取消任务
    • 可以判断任务是否完成
arduino 复制代码
// execute示例
executor.execute(() -> {
    System.out.println("执行任务");
});

// submit示例
Future<String> future = executor.submit(() -> {
    return "任务结果";
});

String result = future.get();  // 获取结果
future.cancel(true);           // 取消任务

总结

核心要点:

  1. 理解参数含义:7个参数决定线程池行为
  2. 掌握工作流程:核心线程 → 队列 → 非核心线程 → 拒绝
  3. 合理配置:根据任务类型(CPU/I/O密集型)配置参数
  4. 避免常见陷阱:内存泄漏、任务饥饿、线程泄露
  5. 善用监控:监控线程池状态,动态调整配置

与之前技术的对比:

技术 特点 适用场景
HandlerThread 单线程,顺序执行 简单后台任务,需要顺序执行
AsyncTask 固定模板,自动线程切换 简单异步任务(已弃用)
IntentService Service + HandlerThread 后台服务,自动停止(已弃用)
ThreadPoolExecutor 灵活配置,强大控制 复杂并发场景,需要精细控制

现代发展趋势:

  1. 协程:更轻量,更简洁的并发方案
  2. WorkManager:替代IntentService的后台任务调度
  3. 响应式编程:RxJava的线程调度器
相关推荐
专注前端30年2 小时前
【PHP开发与安全防护实战】性能调优手册
android·安全·php
王正南3 小时前
安卓逆向之LSposed开发(一)
android·xposed·lsposed
YIN_尹4 小时前
【MySQL】数据类型(上)
android·mysql·adb
robotx6 小时前
AOSP设备节点权限添加相关
android
顾林海6 小时前
Android文件系统安全与权限控制:给应用数据上把“安全锁”
android·面试·操作系统
青莲8436 小时前
Android 动画机制完整详解
android·前端·面试
城东米粉儿6 小时前
android 离屏预渲染 笔记
android
未知名Android用户6 小时前
Android自定义 View + Canvas—声纹小球动画
android
_李小白6 小时前
【Android FrameWork】延伸阅读:AMS 的 handleApplicationCrash
android·开发语言·python