java面试常问
1.如何创建线程池?线程池常见参数有哪些?
一句话总结
创建线程池可通过Java的ThreadPoolExecutor构造函数或Executors工具类实现。核心参数包括:核心线程数(维持常驻线程)、最大线程数(扩容上限)、存活时间(非核心线程空闲时长)、任务队列(存放待执行任务)、拒绝策略(队列满时的处理方式)。
详细解析
一、线程池的创建方式
在 Java 中,线程池的创建主要有两种方式:通过Executors工厂类快速创建和通过ThreadPoolExecutor手动配置。推荐生产环境中使用后者以实现精细化控制。
- 通过Executors工厂类创建(快速实现)
• 固定大小线程池
适用于负载稳定的场景(如 API 请求处理):
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5); // 核心线程数=最大线程数=5
• 可缓存线程池
适用于大量短生命周期任务(如批量数据处理):
ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); // 线程数动态调整
• 单线程线程池
保证任务顺序执行(如事务处理):
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
• 定时/周期性线程池
用于延迟或周期性任务调度(如心跳检测):
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
scheduledThreadPool.scheduleAtFixedRate(() -> {
System.out.println("定时任务执行");
}, 0, 2, TimeUnit.SECONDS);通过ThreadPoolExecutor手动配置(推荐生产环境)
2. 通过ThreadPoolExecutor手动配置(推荐生产环境)
直接配置核心参数,灵活控制线程池行为:
int corePoolSize = 5; // 核心线程数
int maxPoolSize = 10; // 最大线程数
long keepAliveTime = 60L; // 空闲线程存活时间
TimeUnit unit = TimeUnit.SECONDS;
BlockingQueue
二、线程池核心参数详解
参数 作用 配置建议 典型场景
corePoolSize 核心线程数,线程池长期保持的最小线程数 CPU 密集型任务设为 CPU 核心数;I/O 密集型任务设为2 * CPU 核心数 高并发 I/O 任务(如 Web 服务器)
maximumPoolSize 最大线程数,线程池允许的最大并发线程数 根据系统资源(内存、CPU)和任务类型调整,避免资源耗尽 突发流量场景(如秒杀)
keepAliveTime 非核心线程空闲存活时间 结合任务间隔设置(如 60 秒),及时回收空闲线程 低频任务(如定时任务)
unit keepAliveTime的时间单位 常用TimeUnit.SECONDS或TimeUnit.MILLISECONDS 与业务需求匹配
workQueue 任务队列,存放待执行的任务 优先使用有界队列(如LinkedBlockingQueue),避免内存溢出 任务量波动较大的场景
threadFactory 线程工厂,用于创建线程 自定义线程名称、优先级等,便于监控和调试 需追踪线程来源的生产环境
handler 拒绝策略,当队列满且线程数达上限时的处理方式 根据业务需求选择策略(如丢弃、抛出异常、由调用线程执行) 高负载下的容错处理
三、线程池参数配置最佳实践
核心线程数(corePoolSize)
• CPU 密集型任务:设置为CPU 核心数(如Runtime.getRuntime().availableProcessors())。
• I/O 密集型任务:设置为2 * CPU 核心数(因线程等待 I/O 时释放 CPU)。
任务队列(workQueue)
• 有界队列(如LinkedBlockingQueue):防止内存溢出,需设置合理容量。
• 无界队列(如SynchronousQueue):适用于任务直接交接的场景,但可能引发 OOM。
拒绝策略(handler)
策略 行为 适用场景
AbortPolicy(默认) 抛出RejectedExecutionException异常 需快速失败并记录日志的场景
CallerRunsPolicy 由提交任务的线程直接执行任务 任务可降级处理的场景
DiscardPolicy 直接丢弃任务,不抛出异常 可容忍任务丢失的场景
DiscardOldestPolicy 丢弃队列头部任务,尝试重新提交当前任务 需优先处理新任务的场景
线程工厂(threadFactory)
• 自定义线程名称,便于排查问题:
ThreadFactory threadFactory = r -> {
Thread thread = new Thread(r);
thread.setName("custom-thread-" + UUID.randomUUID());
return thread;
};