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 9 Optional API 新增方法

    浅析Java 9 Optional API 新增方法

    本文我们介绍了Java 9 Optional Api新增的三个方法。or方法在Optional为空时返回Optional对象。 ifPresentOrElse()在值存在时执行Consumer参数,反之执行另一个参数回调参数。感兴趣的朋友跟随小编一起看看吧
    2019-12-12
  • Java资源缓存 之 LruCache

    Java资源缓存 之 LruCache

    LruCache (此类在android-support-v4的包中提供) 这个类非常适合用来缓存图片,它的主要算法原理是把最近使用的对象用强引用存储在 LinkedHashMap 中,并且把最近最少使用的对象在缓存值达到预设定值之前从内存中移除。
    2016-08-08
  • java中复杂查询sql语句该怎么写

    java中复杂查询sql语句该怎么写

    我们知道在java连接数据库之后,需要数据库的sql语句,下面这篇文章主要给大家介绍了关于java中复杂查询sql语句该怎么写的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-11-11
  • SpringBoot RestTemplate请求日志打印方式

    SpringBoot RestTemplate请求日志打印方式

    这篇文章主要介绍了SpringBoot RestTemplate请求日志打印方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • JAVA基本类型包装类 BigDecimal BigInteger 的使用

    JAVA基本类型包装类 BigDecimal BigInteger 的使用

    Java 中预定义了八种基本数据类型,包括:byte,int,long,double,float,boolean,char,short,接下来文章小编将向大家介绍其中几个类型的内容,需要的朋友可以参考下文章
    2021-09-09
  • Java日期时间调整的几种方式汇总

    Java日期时间调整的几种方式汇总

    Calendar类是一个抽象类,在实际使用时实现特定的子类的对象,创建对象的过程对程序员来说是透明的,只需要使用getInstance方法创建即可,这篇文章主要介绍了Java日期时间调整的几种方式,需要的朋友可以参考下
    2023-05-05
  • Spring Boot配置application.yml及根据application.yml选择启动配置的操作方法

    Spring Boot配置application.yml及根据application.yml选择启动配置的操作

    Spring Boot中可以选择applicant.properties 作为配置文件,也可以通过在application.yml中进行配置,让Spring Boot根据你的选择进行加载启动配置文件,本文给大家介绍Spring Boot配置application.yml及根据application.yml选择启动配置的操作方法,感兴趣的朋友一起看看吧
    2023-10-10
  • Java Method类及invoke方法原理解析

    Java Method类及invoke方法原理解析

    这篇文章主要介绍了Java Method类及invoke方法原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • MyBatis多表关联查询的实现示例

    MyBatis多表关联查询的实现示例

    本文主要介绍了MyBatis多表关联查询的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • SpringBoot配置web访问H2的方法

    SpringBoot配置web访问H2的方法

    这篇文章主要介绍了SpringBoot配置web访问H2的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08

最新评论