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内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • SpringBoot加载启动的源码解析

    SpringBoot加载启动的源码解析

    这篇文章主要介绍了SpringBoot加载启动的源码解析,@SpringBootApplication注解是Spring Boot的核心注解,它其实是一个组合注解,本身其实也是一个IoC容器的配置类,需要的朋友可以参考下
    2023-12-12
  • Spring定时任务无故停止又不报错的解决

    Spring定时任务无故停止又不报错的解决

    这篇文章主要介绍了Spring定时任务无故停止又不报错的解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • SpringBoot实现其他普通类调用Spring管理的Service,dao等bean

    SpringBoot实现其他普通类调用Spring管理的Service,dao等bean

    这篇文章主要介绍了SpringBoot实现其他普通类调用Spring管理的Service,dao等bean,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • Android仿微信实现左滑显示删除按钮功能

    Android仿微信实现左滑显示删除按钮功能

    这篇文章主要为大家详细介绍了java仿微信实现左滑显示删除按钮功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-10-10
  • idea中如何查看类中所有方法列表

    idea中如何查看类中所有方法列表

    这篇文章主要介绍了idea中如何查看类中所有方法列表问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • Struts1和struts2的区别_动力节点Java学院整理

    Struts1和struts2的区别_动力节点Java学院整理

    这篇文章主要为大家详细介绍了Struts1和struts2的区别,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-09-09
  • 在Java中避免NullPointerException的解决方案

    在Java中避免NullPointerException的解决方案

    这篇文章主要介绍了在Java中避免NullPointerException的解决方案,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • Java编程用两个栈实现队列代码分享

    Java编程用两个栈实现队列代码分享

    这篇文章主要介绍了Java编程用两个栈实现队列代码分享,具有一定参考价值,这里给大家分享下,供需要的朋友了解。
    2017-10-10
  • Jmeter参数化实现方法及应用实例

    Jmeter参数化实现方法及应用实例

    这篇文章主要介绍了Jmeter参数化实现方法及应用实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • SpringBoot整合XxlJob分布式任务调度平台

    SpringBoot整合XxlJob分布式任务调度平台

    xxl-job是一个开源的分布式定时任务框架,它可以与其他微服务组件一起构成微服务集群。它的调度中心(xxl-job)和执行器(自己的springboot项目中有@XxlJob("定时任务名称")的方法)是相互分离,分开部署的,两者通过HTTP协议进行通信
    2023-02-02

最新评论