首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

线程管理神器:Executors全面解析

线程管理神器:Executors全面解析- 程序员古德内容摘要

Executors在Java中提供了快速创建线程池的能力,其优点显著:它简化了线程管理,减少了代码量;提供了多种类型的线程池以适应不同场景;通过复用线程,降低了资源消耗,提高了系统响应速度和吞吐量。使用Executors,开发者能够更专注于业务逻辑,而无需深入底层线程细节。

官方文档:https://docx.iamqiang.com/jdk11/api/java.base/java/util/concurrent/Executors.html

核心概念

在Java中,Executors 是一个提供线程池功能的实用工具类,它允许更便捷地创建、管理和控制线程,从而优化资源使用和提高系统性能。

模拟一个例子,假如有一个公司的电商平台即将开始双十一大促互动,大促活动预计将带来前所未有的流量和订单量,在这种情况下,为了确保系统的稳定性和高效性,不能简单地为每个用户请求都创建一个新线程来处理,因为这样做会消耗大量系统资源,并且可能导致服务器崩溃,这是可以使用Executors。

可以将Executors想象成一家高效的物流公司,当电商平台接收到用户订单时(就像物流公司接收到货物一样),不是直接为每个订单派一辆独立的货车去送货(这相当于为每个请求创建一个新线程),而是将这些订单放入一个集中的处理中心(线程池)。

这个处理中心(线程池)由Executors管理,它会根据当前的订单量(任务量)和系统资源情况,智能地分配有限的货车(线程)去送货(执行任务),如果订单量激增,Executors会自动排队并管理这些订单,确保每个订单都能得到及时处理,同时避免资源的浪费和系统的崩溃。

使用Executors可以更高效地管理线程,特别是在处理大量并发任务时,它能够显著提升系统的性能和稳定性。

代码案例

如下是一个Executors的使用案例,展示了用一个固定大小的线程池来并发执行任务,如下代码:

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.TimeUnit;

public class ThreadPoolExample {

public static void main(String[] args) {

// 创建一个固定大小的线程池,其中包含了3个线程

ExecutorService executorService = Executors.newFixedThreadPool(3);

// 提交10个任务到线程池

for (int i = 0; i < 10; i++) {

final int taskId = i;

executorService.submit(() -> {

// 模拟任务执行,这里简单地打印任务ID和执行的线程名

System.out.println("Executing task " + taskId + " via " + Thread.currentThread().getName());

try {

// 让线程休眠一段时间,模拟任务耗时

Thread.sleep(1000);

} catch (InterruptedException e) {

// 如果线程被中断,则处理中断

e.printStackTrace();

}

});

}

// 关闭线程池(这会让线程池不再接受新的任务,但会继续处理队列中的任务)

executorService.shutdown();

// 等待所有任务完成(这里等待的时间比所有任务的总执行时间要长,以确保所有任务都能完成)

try {

if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {

// 如果等待超时后线程池仍未关闭,可以选择执行一些额外的操作,比如取消剩余任务

System.err.println("Not all tasks finished in the given time.");

}

} catch (InterruptedException ie) {

// 如果当前线程在等待过程中被中断,则处理中断

System.err.println("Interrupted while waiting for tasks to complete.");

// 重新设置中断状态,以便调用者能够知道发生了中断

Thread.currentThread().interrupt();

}

System.out.println("All tasks are finished.");

}

}

在上面代码中,通过Executors.newFixedThreadPool(3)创建了一个包含3个线程的线程池,然后提交了10个任务到线程池,每个任务都简单地打印出任务ID和执行它的线程名,然后休眠1秒钟来模拟任务执行。

这里实例中的代码是非常简单的,并且只是为了演示线程池的基本用法,在实际应用中,可能会有更复杂和耗时的任务需要处理。

核心API说明

newFixedThreadPool(int nThreads):创建一个固定大小的线程池,该线程池中的线程数量始终保持不变,如果所有线程都在执行任务并且又有新任务提交,那么新任务会进入队列等待,直到有线程空闲出来,如果线程因为异常结束,那么会有新的线程来替代它。

newCachedThreadPool():创建一个可缓存的线程池,如果线程池的大小超过了处理需求,那么会回收空闲线程(60秒无任务的线程),当提交新任务时,如果没有空闲线程,那么会创建新的线程,该线程池的大小可以动态调整。

newSingleThreadExecutor():创建一个单线程的 ExecutorService,所有提交的任务都会按照这个顺序在一个线程中执行,如果该线程因为异常结束,那么会有新的线程来替代它。

newSingleThreadScheduledExecutor():创建一个单线程的 ScheduledExecutorService,该线程池可以调度在给定的延迟后执行命令,或者定期执行命令。

newScheduledThreadPool(int corePoolSize):创建一个可以调度在给定的延迟后执行命令,或者定期执行命令的线程池,该线程池的核心线程数量是固定的,但非核心线程数量可以动态调整(基于工作队列的大小和任务提交的速度)。

注意:尽管 Executors 提供了方便的工厂方法来创建线程池,但在生产环境中,建议使用 ThreadPoolExecutor 的直接构造方法来创建线程池,这样可以更细粒度地控制线程池的参数和配置。

另外,从Java 9开始,Executors 类中增加了 newWorkStealingPool 方法,用于创建一个工作窃取线程池,这在处理大量并行任务时非常有用,特别是当任务的执行时间不确定时。工作窃取算法可以帮助平衡各个线程之间的工作量,从而提高整体的吞吐量。

核心总结

线程管理神器:Executors全面解析 - 程序员古德

Executors是Java中创建线程池的便捷工具,其优点在于提供了多种类型的线程池以满足不同场景的需求,如固定大小、缓存、单线程等,这些线程池减少了资源管理的复杂性,并提供了性能优势,然而,Executors的缺点在于其默认配置可能不适合所有场景,如工作队列大小和拒绝策略等,在复杂场景中,优先考虑使用ThreadPoolExecutor以获得更多的线程控制权。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OSq-53lUmf2OqyRVVPfFAHxA0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券