橄榄球世界杯_1990世界杯阿根廷 - liuweiqing95511.com

橄榄球世界杯_1990世界杯阿根廷 - liuweiqing95511.com

【多线程篇20】:线程池的类型和基本API详细整理

Home 2025-09-23 19:54:42 【多线程篇20】:线程池的类型和基本API详细整理

【多线程篇20】:线程池的类型和基本API详细整理

文章目录 一、线程池的基本类型`Executors`类创建线程池`ThreadPoolExecutor` 的核心参数 二、线程池的基本API大全`Executor` 接口`ExecutorService` 接口 (继

  • admin 今晚世界杯直播
  • 2025-09-23 19:54:42

文章目录

一、线程池的基本类型`Executors`类创建线程池`ThreadPoolExecutor` 的核心参数

二、线程池的基本API大全`Executor` 接口`ExecutorService` 接口 (继承自`Executor`)`ScheduledExecutorService` 接口 (继承自`ExecutorService`)

三、总结

一、线程池的基本类型

Java中线程池的创建主要通过java.util.concurrent.Executors工具类提供的静态方法或者直接通过java.util.concurrent.ThreadPoolExecutor类来构造

Executors类创建线程池

Executors类提供的几种常见线程池类型是ThreadPoolExecutor的预配置实例,它们各有侧重。

FixedThreadPool (固定大小线程池)

创建方式: Executors.newFixedThreadPool(int nThreads)特点:

创建固定数量的线程。当所有线程都在忙碌时,新提交的任务会进入一个无界队列(LinkedBlockingQueue)等待。适用于需要控制并发线程数量的场景,例如限制服务器的并发请求处理能力。 核心参数:

corePoolSize = nThreadsmaximumPoolSize = nThreadskeepAliveTime = 0L (对核心线程无效,因为核心线程不会被回收)workQueue = new LinkedBlockingQueue() (无界队列) 优点: 资源消耗可控,避免线程过多导致系统崩溃。缺点: 无界队列可能导致内存溢出(OOM)问题,如果任务提交速度远大于处理速度。 SingleThreadExecutor (单线程线程池)

创建方式: Executors.newSingleThreadExecutor()特点:

只有一个工作线程。所有任务按照提交顺序依次执行。适用于需要保证任务顺序执行的场景。 核心参数:

corePoolSize = 1maximumPoolSize = 1keepAliveTime = 0LworkQueue = new LinkedBlockingQueue() (无界队列) 优点: 保证任务顺序执行,无需担心并发问题。缺点: 同FixedThreadPool,无界队列可能导致内存溢出。 CachedThreadPool (可缓存线程池)

创建方式: Executors.newCachedThreadPool()特点:

线程数量不固定,按需创建。当有任务提交时,如果现有线程可用,则复用;如果没有可用线程,则创建新线程。当线程空闲超过keepAliveTime(默认60秒)时,会被回收。适用于任务量小、执行时间短、但突发性强的场景。 核心参数:

corePoolSize = 0 (无核心线程)maximumPoolSize = Integer.MAX_VALUE (几乎无限制)keepAliveTime = 60Lunit = TimeUnit.SECONDSworkQueue = new SynchronousQueue() (不存储任务的队列,直接将任务交给线程执行,如果没有可用线程,则创建新线程) 优点: 自动扩容和回收,提高资源利用率。缺点: maximumPoolSize过大可能导致创建过多线程,消耗大量系统资源,甚至OOM。 ScheduledThreadPool (定时任务线程池)

创建方式: Executors.newScheduledThreadPool(int corePoolSize)特点:

用于执行定时任务或周期性任务。可以设置延迟执行任务,或者周期性地执行任务。 核心参数:

corePoolSize = corePoolSize (指定核心线程数)maximumPoolSize = Integer.MAX_VALUEkeepAliveTime = 0LworkQueue = new DelayedWorkQueue() (延迟队列) 优点: 方便实现定时任务。缺点: maximumPoolSize过大可能导致创建过多线程。

注意: Executors工具类创建的线程池,除了ScheduledThreadPool可以指定核心线程数外,其他三种(FixedThreadPool, SingleThreadExecutor, CachedThreadPool)在某些场景下可能存在隐患(如OOM),因此在生产环境中,更推荐直接使用ThreadPoolExecutor的构造方法来自定义线程池,以更精确地控制线程池的各项参数。

ThreadPoolExecutor 的核心参数

ThreadPoolExecutor的构造方法有多个重载,最常用的是包含以下参数的构造方法:

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue workQueue,

ThreadFactory threadFactory,

RejectedExecutionHandler handler)

corePoolSize: 核心线程数。当提交一个任务时,如果当前运行的线程少于corePoolSize,则创建新线程来执行任务,即使有空闲线程。maximumPoolSize: 最大线程数。当工作队列已满,并且当前运行的线程数少于maximumPoolSize时,线程池会创建新线程来处理任务。keepAliveTime: 非核心线程的空闲时间。当线程池中的线程数量超过corePoolSize时,如果这些多余的线程空闲时间超过keepAliveTime,它们将被终止并从线程池中移除。unit: keepAliveTime的时间单位(如TimeUnit.SECONDS)。workQueue: 任务队列。当corePoolSize的线程都在忙碌时,新提交的任务会被放入这个队列等待执行。

ArrayBlockingQueue: 基于数组的有界阻塞队列。LinkedBlockingQueue: 基于链表的阻塞队列,可以有界也可以无界(默认无界)。SynchronousQueue: 不存储元素的阻塞队列,每个插入操作必须等待一个对应的移除操作。PriorityBlockingQueue: 具有优先级的无界阻塞队列。 threadFactory: 线程工厂。用于创建新线程。可以自定义线程的命名、优先级等。handler: 拒绝策略。当线程池和工作队列都满了,无法再接受新任务时,会根据拒绝策略进行处理。

ThreadPoolExecutor.AbortPolicy (默认): 抛出RejectedExecutionException异常。ThreadPoolExecutor.CallerRunsPolicy: 调用者线程自己执行该任务。ThreadPoolExecutor.DiscardOldestPolicy: 丢弃队列中最老的任务,然后尝试提交当前任务。ThreadPoolExecutor.DiscardPolicy: 直接丢弃当前任务,不抛出异常。

二、线程池的基本API大全

线程池的主要API集中在Executor、ExecutorService和ScheduledExecutorService接口中,ThreadPoolExecutor实现了ExecutorService接口

Executor 接口

void execute(Runnable command):

提交一个Runnable任务到线程池执行Runnable任务没有返回值

ExecutorService 接口 (继承自Executor)

void shutdown():

平滑关闭线程池不再接受新任务,但会等待已提交的任务(包括队列中的任务)执行完成此方法调用后,isShutdown()返回true,isTerminated()返回false(直到所有任务执行完毕) List shutdownNow():

立即关闭线程池尝试停止所有正在执行的任务,并返回等待执行的任务列表此方法调用后,isShutdown()返回true,isTerminated()可能立即返回true,也可能需要等待一小段时间 boolean isShutdown():

判断线程池是否已关闭(即是否调用过shutdown()或shutdownNow()) boolean isTerminated():

判断线程池是否已终止(即所有任务都已完成,并且线程池已关闭) boolean awaitTermination(long timeout, TimeUnit unit):

阻塞当前线程,直到线程池终止、超时或当前线程被中断通常在调用shutdown()之后使用,用于等待线程池中的任务完成返回true表示线程池已终止,false表示超时 Future submit(Callable task):

提交一个Callable任务到线程池执行Callable任务有返回值,返回一个Future对象,可以通过Future.get()获取任务执行结果 Future submit(Runnable task):

提交一个Runnable任务到线程池执行虽然Runnable没有返回值,但此方法仍然返回一个Future对象,可以通过Future.get()来判断任务是否完成(返回null) Future submit(Runnable task, T result):

提交一个Runnable任务到线程池执行,并指定一个结果对象当任务完成时,Future.get()将返回这个指定的结果对象 List> invokeAll(Collection> tasks):

批量提交多个Callable任务阻塞当前线程,直到所有任务都完成,或者超时返回一个Future列表,每个Future对应一个任务的结果 List> invokeAll(Collection> tasks, long timeout, TimeUnit unit):

同上,但增加了超时机制 T invokeAny(Collection> tasks):

批量提交多个Callable任务阻塞当前线程,直到其中一个任务成功完成(或抛出异常),并返回该任务的结果。其他未完成的任务会被取消 T invokeAny(Collection> tasks, long timeout, TimeUnit unit):

同上,但增加了超时机制

ScheduledExecutorService 接口 (继承自ExecutorService)

ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit):

在指定的延迟时间后执行一次Runnable任务 ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit):

在指定的延迟时间后执行一次Callable任务 ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit):

以固定的频率周期性执行Runnable任务initialDelay: 首次执行的延迟时间period: 连续两次任务开始执行之间的时间间隔(固定频率)如果任务执行时间超过period,则下一个任务会立即开始执行(不会等待上一个任务完成后的period) ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit):

以固定的延迟周期性执行Runnable任务initialDelay: 首次执行的延迟时间delay: 上一个任务执行结束后到下一个任务开始执行之间的延迟时间(固定延迟)

三、总结

ThreadPoolExecutor 的运行机制

核心: 理解线程池如何根据 corePoolSize、maximumPoolSize、workQueue 和拒绝策略协同工作,以决定是创建新线程、将任务放入队列还是执行拒绝策略流程: 任务提交后,首先判断当前运行线程数是否小于 corePoolSize;若小于,则创建核心线程执行任务。若不小于,则尝试将任务放入 workQueue;若队列已满,则判断当前运行线程数是否小于 maximumPoolSize;若小于,则创建非核心线程执行任务。若仍不满足,则执行拒绝策略建议: 能够清晰地画出或描述任务在线程池中的流转图 线程池的拒绝策略

核心: 掌握 ThreadPoolExecutor 内置的四种拒绝策略 (AbortPolicy, CallerRunsPolicy, DiscardOldestPolicy, DiscardPolicy) 的具体行为和应用场景自定义: 了解如何通过实现 RejectedExecutionHandler 接口来自定义拒绝策略,以满足特定业务需求(例如,记录日志、降级处理等)建议: 能够结合实际场景说明选择不同拒绝策略的理由 如何合理设置线程池参数

核心: 理解线程池参数设置的原则,特别是 corePoolSize 和 maximumPoolSize 的设置,应根据任务的类型(CPU密集型或IO密集型)进行调整

CPU密集型: 核心线程数 通常设置为 CPU核心数 + 1 或 CPU核心数。因为任务主要消耗CPU,过多的线程会导致频繁的上下文切换,降低效率IO密集型: 核心线程数 通常设置为 2 * CPU核心数 或 CPU核心数 / (1 - 阻塞系数)。因为IO操作会阻塞线程,线程在等待IO时可以让出CPU给其他线程,因此可以设置更多的线程来提高吞吐量 建议: 能够结合具体案例分析如何进行参数估算和设置 线程池的监控与调优

核心: 了解如何获取线程池的实时状态信息,例如 getPoolSize() (当前线程池线程总数)、getActiveCount() (当前活动线程数)、getQueue().size() (队列中等待任务数)、getCompletedTaskCount() (已完成任务数) 等调优: 根据监控数据(如任务等待时间过长、CPU使用率过高、内存占用异常等)进行参数调整,例如增加或减少线程数、调整队列类型或大小、优化任务逻辑等建议: 知道一些基本的监控工具或方法(如JMX、自定义日志),并能描述简单的调优思路 线程池的关闭 (shutdown() vs shutdownNow())

核心: 明确 shutdown() 和 shutdownNow() 方法的区别和适用场景

shutdown(): 平滑关闭,不再接受新任务,但会等待已提交的任务(包括队列中的)执行完成shutdownNow(): 立即关闭,尝试中断所有正在执行的任务,并返回未执行的任务列表 配合使用: 了解 awaitTermination() 方法,通常在调用 shutdown() 后使用,用于等待线程池中的任务完成,以确保资源的正确释放建议: 能够说明在应用程序退出时如何优雅地关闭线程池 Runnable 和 Callable 的区别

核心: 理解两者在任务执行结果和异常处理上的差异

Runnable: 接口定义 void run() 方法,无返回值,无法抛出受检查异常Callable: 接口定义 V call() 方法,有返回值,可以抛出受检查异常 使用场景: 根据是否需要返回值或处理异常来选择合适的任务类型建议: 能够写出使用这两种接口的简单示例 Future 的作用和使用

核心: 理解 Future 对象是异步计算的结果,它提供了检查任务是否完成、等待任务完成以及获取任务结果的方法主要方法: get() (阻塞获取结果,可能抛出 ExecutionException 或 InterruptedException)、isDone() (判断任务是否完成)、isCancelled() (判断任务是否被取消)、cancel() (尝试取消任务)建议: 能够结合 submit() 方法说明 Future 的使用方式,并讨论其在异步编程中的重要性 为什么不推荐直接使用 Executors 创建的线程池(生产环境)

核心: 理解 Executors 提供的便捷方法(如 newFixedThreadPool、newSingleThreadExecutor、newCachedThreadPool)在生产环境中可能存在的隐患

FixedThreadPool 和 SingleThreadExecutor: 使用了无界队列 LinkedBlockingQueue,可能导致内存溢出 (OOM),当任务提交速度远超处理速度时CachedThreadPool: maximumPoolSize 设置为 Integer.MAX_VALUE,可能创建过多线程,导致系统资源耗尽 (OOM) 或频繁上下文切换,影响性能ScheduledThreadPool: maximumPoolSize 同样过大 建议: 强调在生产环境中,应通过 ThreadPoolExecutor 的构造方法来自定义线程池,以精确控制线程数量、队列类型和拒绝策略,从而避免潜在的资源问题和提高稳定性

  • 监控需要设备密码忘记了怎么办
Copyright © 2088 橄榄球世界杯_1990世界杯阿根廷 - liuweiqing95511.com All Rights Reserved.
友情链接