在Android开发中,合理配置线程池参数是优化应用性能、避免内存溢出和ANR的关键。一个配置不当的线程池可能导致资源浪费、性能下降甚至应用崩溃。本文将深入探讨如何科学配置线程池参数。该文也解答了博文Android线程与线程池面试题总结中3.4节的问题。
// 线程池构造函数
public ThreadPoolExecutor(
int corePoolSize, // 核心线程数
int maximumPoolSize, // 最大线程数
long keepAliveTime, // 线程空闲时间
TimeUnit unit, // 时间单位
BlockingQueue<Runnable> workQueue, // 工作队列
ThreadFactory threadFactory, // 线程工厂
RejectedExecutionHandler handler // 拒绝策略
)
CPU密集型任务
特点: 大量计算,CPU使用率高。示例: 图像处理、复杂算法、数据加密建议:线程数不宜过多,避免频繁上下文切换IO密集型任务
特点: 大量等待时间,CPU使用率低。示例: 网络请求,文件读写、数据库操作建议: 可配置较多线程,充分利用等待时间混合型任务
特点:既有计算又有IO操作建议:根据具体比例调整CPU密集型任务配置
public class CpuIntensiveThreadPool {
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// 核心公式:corePoolSize = CPU核心数 + 1
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final long KEEP_ALIVE_TIME = 30L;
public static ThreadPoolExecutor create() {
return new ThreadPoolExecutor(
CORE_POOL_SIZE,
MAXIMUM_POOL_SIZE,
KEEP_ALIVE_TIME,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(128),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
}
}
IO密集型任务配置
public class IoIntensiveThreadPool {
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// 核心公式:corePoolSize = 2 * CPU核心数
private static final int CORE_POOL_SIZE = CPU_COUNT * 2;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 4;
private static final long KEEP_ALIVE_TIME = 60L;
public static ThreadPoolExecutor create() {
return new ThreadPoolExecutor(
CORE_POOL_SIZE,
MAXIMUM_POOL_SIZE,
KEEP_ALIVE_TIME,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(256),
new CustomThreadFactory("IO-Thread"),
new ThreadPoolExecutor.CallerRunsPolicy()
);
}
}
混合型任务配置
public class MixedTaskThreadPool {
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// 根据IO与CPU比例动态调整
public static ThreadPoolExecutor create(float ioRatio) {
int baseSize = Math.max(2, CPU_COUNT);
int coreSize = (int) (baseSize * (1 + ioRatio));
return new ThreadPoolExecutor(
coreSize,
coreSize * 2,
45L,
TimeUnit.SECONDS,
new PriorityBlockingQueue<Runnable>(),
new CustomThreadFactory("Mixed-Thread"),
new CustomRejectedExecutionHandler()
);
}
}
// 有界队列 - 防止内存溢出
new ArrayBlockingQueue<Runnable>(capacity)
// 无界队列 - 可能引起OOM
new LinkedBlockingQueue<Runnable>()
// 同步移交队列 - 适合任务量大的场景
new SynchronousQueue<Runnable>()
// 直接抛出异常
new ThreadPoolExecutor.AbortPolicy()
// 调用者线程执行
new ThreadPoolExecutor.CallerRunsPolicy()
// 丢弃最老任务
new ThreadPoolExecutor.DiscardOldestPolicy()
// 静默丢弃
new ThreadPoolExecutor.DiscardPolicy()
public class CustomThreadFactory implements ThreadFactory {
private final String namePrefix;
private final AtomicInteger threadNumber = new AtomicInteger(1);
public CustomThreadFactory(String poolName) {
namePrefix = poolName + "-";
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, namePrefix + threadNumber.getAndIncrement());
t.setPriority(Thread.NORM_PRIORITY - 1);
t.setDaemon(false);
return t;
}
}
public class ThreadPoolMonitor {
public static void monitor(ThreadPoolExecutor executor) {
// 核心监控指标
int corePoolSize = executor.getCorePoolSize();
int activeCount = executor.getActiveCount();
long completedTaskCount = executor.getCompletedTaskCount();
long taskCount = executor.getTaskCount();
int queueSize = executor.getQueue().size();
// 计算线程池利用率
double utilization = (double) activeCount / corePoolSize;
Log.d("ThreadPoolMonitor",
String.format("Active: %d, Queue: %d, Completed: %d, Utilization: %.2f",
activeCount, queueSize, completedTaskCount, utilization));
}
}
public class DynamicThreadPool {
private ThreadPoolExecutor executor;
public void adjustBasedOnLoad() {
int activeCount = executor.getActiveCount();
int queueSize = executor.getQueue().size();
if (queueSize > 100 && activeCount == executor.getMaximumPoolSize()) {
// 队列积压严重,考虑调整参数
executor.setMaximumPoolSize(executor.getMaximumPoolSize() + 2);
} else if (queueSize == 0 && activeCount < executor.getCorePoolSize() / 2) {
// 负载较低,适当收缩
executor.setCorePoolSize(Math.max(2, executor.getCorePoolSize() - 1));
}
}
}
public class ImageLoadThreadPool {
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 * 2 + 1;
private static final ThreadPoolExecutor IMAGE_LOAD_EXECUTOR =
new ThreadPoolExecutor(
CORE_POOL_SIZE,
MAX_POOL_SIZE,
30L, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(50),
new CustomThreadFactory("ImageLoader"),
new ThreadPoolExecutor.DiscardPolicy()
);
public static void loadImage(String url, ImageView imageView) {
IMAGE_LOAD_EXECUTOR.execute(new ImageLoadTask(url, imageView));
}
}
public class NetworkThreadPool {
private static final int CORE_POOL_SIZE = 4; // 网络连接数限制
private static final int MAX_POOL_SIZE = 8;
private static final ThreadPoolExecutor NETWORK_EXECUTOR =
new ThreadPoolExecutor(
CORE_POOL_SIZE,
MAX_POOL_SIZE,
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(100),
new CustomThreadFactory("Network"),
new ThreadPoolExecutor.CallerRunsPolicy()
);
}
线程池参数配置没有银弹,需要根据具体业务场景、设备性能和用户需求综合考虑。建议:
从经验公式开始通过压测验证线上监控调整不同功能使用独立线程池记住:合理的线程池配置是应用性能优化的基础,需要持续观察和优化。
参考资料:
Android官方文档《Java并发编程实战》美团技术团队《线程池实践》