Java中Executor和Executors的区别小结

 更新时间:2024年10月13日 09:26:25   作者:Flying_Fish_Xuan  
在Java并发编程中,Executor是一个核心接口,提供了任务执行的抽象方法,而Executors是一个工具类,提供了创建各种线程池的工厂方法,Executor关注任务的执行,而Executors关注如何创建适合的执行器,感兴趣的可以了解一下

在Java并发编程中,ExecutorExecutors是两个密切相关但功能不同的类或接口,它们都与线程池管理和任务执行相关。理解这两者的区别对正确使用Java并发API非常重要。

1. Executor 的定义与功能

1.1 Executor 接口

Executor 是 Java 并发框架中的一个核心接口,它提供了一种将任务的提交与任务的执行解耦的机制。换句话说,Executor接口的设计目标是将“任务的执行”这一行为抽象出来,使得任务的提交者不必关心任务是如何执行的(如是否在新的线程中执行、是否在某个线程池中执行等)。

public interface Executor {
    void execute(Runnable command);
}

execute(Runnable command) 方法:这是 Executor 接口中唯一的方法,它接受一个实现了 Runnable 接口的任务,并安排该任务的执行。具体如何执行这个任务,由实现 Executor 接口的类决定。

1.2 Executor 接口的设计目的

Executor接口的主要设计目的是简化并发任务的执行过程,提供了一种统一的方式来提交任务,而不需要开发者显式地创建和管理线程。通过这一接口,开发者可以将任务的执行策略(如线程池、异步执行等)与业务逻辑分离,使得代码更简洁、可维护性更高。

2. Executors 的定义与功能

2.1 Executors 类

Executors 是一个实用工具类,它包含了一些静态工厂方法,用于创建 ExecutorExecutorServiceScheduledExecutorService 等的常用实现。这些实现通常与线程池相关,因此 Executors 类在实际开发中非常常用。

public class Executors {
    // 创建一个单线程执行器
    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

    // 创建一个固定线程数的线程池
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

    // 创建一个可以根据需要扩展的线程池
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

    // 其他工厂方法...
}

2.2 Executors 类的常用方法

Executors 类提供了多种创建线程池的方法,每种方法返回的都是 ExecutorService 的不同实现,这些实现适合不同的并发场景:

  • newFixedThreadPool(int nThreads):创建一个固定大小的线程池。这个线程池中的线程数量是固定的,无论有多少任务提交到线程池中,线程池中同时运行的线程数量不会超过指定的大小。适用于处理稳定数量的并发任务。

  • newCachedThreadPool():创建一个可缓存的线程池。这个线程池会根据需要创建新线程,如果线程空闲超过60秒则会被回收,因此在大量短期异步任务的场景中非常有用。

  • newSingleThreadExecutor():创建一个单线程执行器。这个执行器确保所有任务在一个线程中按顺序执行,适用于需要顺序执行任务的场景。

  • newScheduledThreadPool(int corePoolSize):创建一个定时线程池。该线程池支持任务调度和周期性执行,适用于需要定期执行任务的场景。

3. Executor 与 Executors 的区别

3.1 接口与工具类的区别

  • Executor 是接口:Executor 是一个接口,定义了一个任务执行的标准方法 execute(Runnable command)。它提供了一个抽象层,使得任务的提交者无需关心任务是如何被执行的。

  • Executors 是工具类:Executors 是一个工具类,提供了创建各种 ExecutorExecutorService 实现的静态工厂方法。它简化了线程池的创建过程,使得开发者能够方便地获得适合自己应用场景的线程池实现。

3.2 关注点的区别

  • Executor 关注的是任务的执行:Executor 关注如何执行提交的任务,定义了任务执行的标准接口。它是一种行为规范,使得不同的执行器可以被替换而不改变代码的行为。

  • Executors 关注的是如何创建 ExecutorExecutors 关注的是如何创建符合特定需求的线程池或任务执行器。它提供了多种预定义的 Executor 和 ExecutorService 实现,帮助开发者根据不同的并发需求选择合适的执行策略。

3.3 使用场景的区别

  • Executor 的使用场景:Executor 通常用于需要自定义任务执行逻辑的场景,例如自定义任务调度策略、管理任务队列等。开发者可以实现 Executor 接口,定义自己的任务执行器。

  • Executors 的使用场景:Executors 通常用于创建标准的线程池或执行器,适合常见的并发任务执行需求。通过使用 Executors 提供的工厂方法,开发者可以快速创建和使用线程池,而无需关心底层实现细节。

4. 实际使用中的示例

4.1 使用 Executor

假设我们有一个简单的任务调度系统,我们可以使用 Executor 接口来抽象任务的执行过程:

public class SimpleExecutor implements Executor {
    @Override
    public void execute(Runnable command) {
        new Thread(command).start();
    }
}

这个 SimpleExecutor 类实现了 Executor 接口,它在每次接收到任务时都会创建一个新线程来执行任务。这种实现非常简单,但在实际应用中通常会使用更复杂的执行器,例如线程池。

4.2 使用 Executors

通过 Executors 工具类,我们可以很方便地创建一个固定大小的线程池,并提交任务:

public class ExecutorExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(5);

        for (int i = 0; i < 10; i++) {
            executor.execute(new RunnableTask(i));
        }

        executor.shutdown();
    }
}

class RunnableTask implements Runnable {
    private int taskId;

    public RunnableTask(int id) {
        this.taskId = id;
    }

    @Override
    public void run() {
        System.out.println("Executing task " + taskId + " by " + Thread.currentThread().getName());
    }
}

在这个示例中,我们使用 Executors.newFixedThreadPool(5) 创建了一个固定大小为5的线程池,然后提交了10个任务给线程池执行。线程池将自动管理这些任务的执行,并复用线程来处理任务。

5. 总结

在Java并发编程中,ExecutorExecutors虽然名称相似,但它们有着截然不同的职责和用途:

  • Executor 是一个接口,定义了任务执行的标准方法,它是并发编程中任务执行的核心抽象。Executor 让任务的提交者不需要关心任务的具体执行方式,从而实现任务执行与业务逻辑的解耦。

  • Executors 是一个工具类,提供了多种工厂方法来创建不同类型的 Executor 和 ExecutorService 实现。通过使用 Executors 提供的工厂方法,开发者可以轻松创建和管理线程池,以适应各种并发编程需求。

到此这篇关于Java中Executor和Executors的区别小结的文章就介绍到这了,更多相关Java Executor Executors内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • Java使用Request获取请求参数的通用方式详解

    Java使用Request获取请求参数的通用方式详解

    这篇文章主要给大家介绍了关于Java使用Request获取请求参数的通用方式,在Java后端开发中第一步就是获取前端传过来的请求参数,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-01-01
  • Spring用代码来读取properties文件实例解析

    Spring用代码来读取properties文件实例解析

    这篇文章主要介绍了Spring用代码来读取properties文件实例解析,具有一定借鉴价值,需要的朋友可以参考下
    2018-01-01
  • 关于Java的动态代理机制

    关于Java的动态代理机制

    这篇文章主要介绍了关于Java的动态代理机制,动态代理就是,在程序运行期,创建目标对象的代理对象,并对目标对象中的方法进行功能性增强的一种技术,需要的朋友可以参考下
    2023-05-05
  • java读取PHP接口数据的实现方法

    java读取PHP接口数据的实现方法

    下面小编就为大家带来一篇java读取PHP接口数据的实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-08-08
  • Java将文件内容读取为字符串的实现步骤

    Java将文件内容读取为字符串的实现步骤

    在Java编程中,经常需要将文件内容读取为字符串进行处理,比如配置文件读取、文本数据解析等场景,不同版本的Java提供了多种实现方式,同时也有一些外部库可以简化操作,本文给大家介绍了Java将文件内容读取为字符串的实现步骤,需要的朋友可以参考下
    2025-06-06
  • SpringBoot整合Elasticsearch实现全文检索功能

    SpringBoot整合Elasticsearch实现全文检索功能

    本文介绍了使用Elasticsearch进行全文检索的方法,包括环境搭建、分词配置、CRUD操作、高亮查询、分页、聚合等功能,并展示了如何在SpringBoot中整合Elasticsearch以及如何处理常见问题,需要的朋友可以参考下
    2026-04-04
  • Java 精炼解读递归的概念与使用

    Java 精炼解读递归的概念与使用

    一说起递归,我想每个人都不陌生。举个从小就听过的例子:从前有座山,山里有座庙,庙里有个和尚,和尚在讲故事,从前有座山,山里有座庙,庙里有个和尚,和尚在讲故事,从前有座山,要理解递归,就得先了解什么是递归,实际上这句话就是一个递归
    2022-03-03
  • Java中class和Class的区别示例详解

    Java中class和Class的区别示例详解

    class 是java的关键字,在声明java类时使用,Class是java JDK提供的一个类,完整路径为java.lang.Class,下面这篇文章主要给大家介绍了关于Java中class和Class区别的相关资料,需要的朋友可以参考下
    2022-04-04
  • spring boot动态切换数据源的实现

    spring boot动态切换数据源的实现

    这篇文章主要介绍了spring boot动态切换数据源的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • springMVC如何防止表单重复提交详解

    springMVC如何防止表单重复提交详解

    平时开发的项目中经常会遇到表单重复提交,造成数据重复,增加服务器负载,严重甚至会造成服务器宕机,因此有效防止表单重复提交有一定的必要性,这篇文章主要给大家介绍了关于springMVC如何防止表单重复提交的相关资料,需要的朋友可以参考下
    2021-11-11

最新评论